{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "99d90b64-37b4-42af-b839-f8643f81b623",
   "metadata": {},
   "source": [
    "# 导入模块"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "22824757-b461-4fc4-a6ec-756243a5eb46",
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "from numpy import *\n",
    "import numpy as np\n",
    "import numpy.matlib\n",
    "\n",
    "from matplotlib import pyplot as plt\n",
    "import matplotlib"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "7cf914b6-ee4c-44dd-a5bb-fbdba9cdaab2",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[1., 0., 0., 0.],\n",
       "       [0., 1., 0., 0.],\n",
       "       [0., 0., 1., 0.],\n",
       "       [0., 0., 0., 1.]])"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "eye(4)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4651b0da-9fa3-499c-9cf9-7d5bb933edb7",
   "metadata": {},
   "source": [
    "`numpy.array(object, dtype = None, copy = True, order = None, subok = False, ndmin = 0)`\n",
    "\n",
    "名称|描述\n",
    "--:|:--\n",
    "object|数组或嵌套的数列\n",
    "dtype|数组元素的数据类型，可选\n",
    "copy|对象是否需要复制，可选\n",
    "order|创建数组的样式，C为行方向，F为列方向，A为任意方向（默认）\n",
    "subok|默认返回一个与基类类型一致的数组\n",
    "ndmin|指定生成数组的最小维度"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "edae0288-2009-4e7f-bb61-1bd761348c43",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([1, 2, 3])"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "array([1,2,3])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "8ea74d95-42ce-4b3d-89bf-f5db9ec3b89c",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[1, 2],\n",
       "       [3, 4]])"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "array([[1,  2],  [3,  4]])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "d123c126-ddce-42e0-b6f8-0d022df8eda6",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[1, 2, 3, 4, 5]])"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "array([1, 2, 3, 4, 5], ndmin =  2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "e79af4bb-3906-4012-92b4-de15d8cda9b8",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([1.+0.j, 2.+0.j, 3.+0.j])"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "array([1,  2,  3], dtype = complex)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "fc40055e-8ef9-4e8a-a828-341b3c416f8f",
   "metadata": {},
   "source": [
    "# 数据类型\n",
    "\n",
    "名称|描述\n",
    "--:|:--\n",
    "bool_|布尔型数据类型（True 或者 False）\n",
    "int_|默认的整数类型（类似于 C 语言中的 long，int32 或 int64）\n",
    "intc|与 C 的 int 类型一样，一般是 int32 或 int 64\n",
    "intp|用于索引的整数类型（类似于 C 的 ssize_t，一般情况下仍然是 int32 或 int64）\n",
    "int8|字节（-128 to 127）\n",
    "int16|整数（-32768 to 32767）\n",
    "int32|整数（-2147483648 to 2147483647）\n",
    "int64|整数（-9223372036854775808 to 9223372036854775807）\n",
    "uint8|无符号整数（0 to 255）\n",
    "uint16|无符号整数（0 to 65535）\n",
    "uint32|无符号整数（0 to 4294967295）\n",
    "uint64|无符号整数（0 to 18446744073709551615）\n",
    "float_|float64 类型的简写\n",
    "float16|半精度浮点数，包括：1 个符号位，5 个指数位，10 个尾数位\n",
    "float32|单精度浮点数，包括：1 个符号位，8 个指数位，23 个尾数位\n",
    "float64|双精度浮点数，包括：1 个符号位，11 个指数位，52 个尾数位\n",
    "complex_|complex128 类型的简写，即 128 位复数\n",
    "complex64|复数，表示双 32 位浮点数（实数部分和虚数部分）\n",
    "complex128|复数，表示双 64 位浮点数（实数部分和虚数部分）"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6d894ea2-cd29-44ec-a209-d480c97fd457",
   "metadata": {},
   "source": [
    "`numpy.dtype(object, align, copy)`\n",
    "\n",
    "> object - 要转换为的数据类型对象\n",
    "\n",
    "> align - 如果为 true，填充字段使其类似 C 的结构体。\n",
    "\n",
    ">copy - 复制 dtype 对象 ，如果为 false，则是对内置数据类型对象的引用"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "37e1f86d-b879-4732-a5ad-5470faf9d601",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "dtype('int32')"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# int8, int16, int32, int64 四种数据类型可以使用字符串 'i1', 'i2','i4','i8' 代替\n",
    "dtype('<i4')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "d88b50ba-2a40-4861-b46a-2c4c44c73375",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[10 20 30]\n"
     ]
    }
   ],
   "source": [
    "dt = dtype([('age',int8)]) \n",
    "a = array([(10,),(20,),(30,)], dtype = dt) \n",
    "print(a['age'])"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1d82efab-dfc5-4475-b2be-5763b8537f61",
   "metadata": {},
   "source": [
    "# 自定义结构数据类型"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "7c0e7924-8573-45f1-b5a6-70a1871353aa",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[(b'abc', 21, 50.) (b'xyz', 18, 75.)]\n"
     ]
    }
   ],
   "source": [
    "student = dtype([('name','S20'), ('age', 'i1'), ('marks', 'f4')]) \n",
    "a = array([('abc', 21, 50),('xyz', 18, 75)], dtype = student) \n",
    "print(a)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "284c006b-d581-4722-b57e-f98ce57b0d13",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([b'abc', b'xyz'], dtype='|S20')"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a['name']"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "037451e7-f70a-4c86-980c-e4026cc8249c",
   "metadata": {},
   "source": [
    "> 每个内建类型都有一个唯一定义它的字符代码，如下：\n",
    "\n",
    "字符|对应类型\n",
    "--:|:--\n",
    "b|布尔型\n",
    "i|(有符号) 整型\n",
    "u|无符号整型 integer\n",
    "f|浮点型\n",
    "c|复数浮点型\n",
    "m|timedelta（时间间隔）\n",
    "M|datetime（日期时间）\n",
    "O|(Python) 对象\n",
    "S, a|(byte-)字符串\n",
    "U|Unicode\n",
    "V|原始数据 (void)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1fb62fb2-6096-4456-ad25-3a91a450e198",
   "metadata": {},
   "source": [
    "> ndarray 对象属性\n",
    "\n",
    "属性|说明\n",
    "--:|:--\n",
    "ndarray.ndim|秩，即轴的数量或维度的数量\n",
    "ndarray.shape|数组的维度，对于矩阵，n 行 m 列\n",
    "ndarray.size|数组元素的总个数，相当于 .shape 中 n*m 的值\n",
    "ndarray.dtype|ndarray 对象的元素类型\n",
    "ndarray.itemsize|ndarray 对象中每个元素的大小，以字节为单位\n",
    "ndarray.flags|ndarray 对象的内存信息\n",
    "ndarray.real|ndarray元素的实部\n",
    "ndarray.imag|ndarray 元素的虚部\n",
    "ndarray.data|包含实际数组元素的缓冲区，由于一般通过数组的索引获取元素，所以通常不需要使用这个属性。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "21ff4148-1c8b-4520-b5e4-c1413b61eab2",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "1"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a = arange(24)\n",
    "a.ndim"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "87454132-5449-4a72-84e4-44cfcb877d7c",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(24,)"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a.shape"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "10881e30-a9e9-48a5-91d5-db93f72819ff",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 0,  1,  2,  3,  4,  5,  6,  7],\n",
       "       [ 8,  9, 10, 11, 12, 13, 14, 15],\n",
       "       [16, 17, 18, 19, 20, 21, 22, 23]])"
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a.reshape(3,8)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "id": "7e9dcb3c-9040-4aaf-bf01-0edc90d47eeb",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "8"
      ]
     },
     "execution_count": 14,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a.itemsize"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "id": "75961bfa-6c7a-44e0-8dae-9d05dd186b06",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "  C_CONTIGUOUS : True\n",
       "  F_CONTIGUOUS : True\n",
       "  OWNDATA : True\n",
       "  WRITEABLE : True\n",
       "  ALIGNED : True\n",
       "  WRITEBACKIFCOPY : False\n",
       "  UPDATEIFCOPY : False"
      ]
     },
     "execution_count": 15,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a.flags"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "82fed6de-34c4-4832-a5b5-4c2797896f8f",
   "metadata": {},
   "source": [
    "> ndarray.flags 返回 ndarray 对象的内存信息，包含以下属性：\n",
    "\n",
    "属性|描述\n",
    "--:|:--\n",
    "C_CONTIGUOUS (C)|数据是在一个单一的C风格的连续段中\n",
    "F_CONTIGUOUS (F)|数据是在一个单一的Fortran风格的连续段中\n",
    "OWNDATA (O)|数组拥有它所使用的内存或从另一个对象中借用它\n",
    "WRITEABLE (W)|数据区域可以被写入，将该值设置为 False，则数据为只读\n",
    "ALIGNED (A)|数据和所有元素都适当地对齐到硬件上\n",
    "UPDATEIFCOPY (U)|这个数组是其它数组的一个副本，当这个数组被释放时，原数组的内容将被更新"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "084ebbd7-829e-4368-9367-3737555104be",
   "metadata": {},
   "source": [
    "# 创建数组"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "216f35f9-f48a-46e4-bf74-de7f786cd7ef",
   "metadata": {},
   "source": [
    "## numpy.empty\n",
    "\n",
    "> numpy.empty 方法用来创建一个指定形状（shape）、数据类型（dtype）且未初始化的数组\n",
    "\n",
    "`numpy.empty(shape, dtype = float, order = 'C')`\n",
    "\n",
    "参数|描述\n",
    "--:|:--\n",
    "shape|数组形状\n",
    "dtype|数据类型，可选\n",
    "order|有\"C\"和\"F\"两个选项,分别代表，行优先和列优先，在计算机内存中的存储元素的顺序。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "id": "830f7e76-228d-4824-8214-f34c3b965f2a",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[48145104,        0],\n",
       "       [       0,        0],\n",
       "       [       0,        0]])"
      ]
     },
     "execution_count": 16,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "empty([3,2], dtype = int)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7b9ee0f1-ccb7-419a-aef2-415e09147932",
   "metadata": {},
   "source": [
    "## numpy.zeros\n",
    "\n",
    "> 创建指定大小的数组，数组元素以 0 来填充：\n",
    "\n",
    "`numpy.zeros(shape, dtype = float, order = 'C')`\n",
    "\n",
    "参数|描述\n",
    "--:|:--\n",
    "shape|数组形状\n",
    "dtype|数据类型，可选\n",
    "order|'C' 用于 C 的行数组，或者 'F' 用于 FORTRAN 的列数组"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "id": "0bbeb44b-d99b-4f46-9583-111b9dd81978",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([0., 0., 0., 0., 0.])"
      ]
     },
     "execution_count": 17,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "zeros(5)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "id": "f4c36352-9a6c-427d-9721-76daa8da2279",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([0, 0, 0, 0, 0])"
      ]
     },
     "execution_count": 18,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "zeros((5,), dtype = int)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "id": "bb0bb411-00c2-4a8a-a18a-6d88d46dc748",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[(0, 0), (0, 0)],\n",
       "       [(0, 0), (0, 0)]], dtype=[('x', '<i4'), ('y', '<i4')])"
      ]
     },
     "execution_count": 19,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "zeros((2,2), dtype = [('x', 'i4'), ('y', 'i4')])"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "fb4e8ad0-80ac-4ae9-8c09-d9fb0f2fdbd4",
   "metadata": {},
   "source": [
    "## numpy.ones\n",
    "\n",
    "> 创建指定形状的数组，数组元素以 1 来填充：\n",
    "\n",
    "`numpy.ones(shape, dtype = None, order = 'C')`\n",
    "\n",
    "参数|描述\n",
    "--:|:--\n",
    "shape|数组形状\n",
    "dtype|数据类型，可选\n",
    "order|'C' 用于 C 的行数组，或者 'F' 用于 FORTRAN 的列数组"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "id": "1cdf230f-aef4-4cfa-ac15-470cd1b5564b",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([1., 1., 1., 1., 1.])"
      ]
     },
     "execution_count": 20,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "ones(5)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "id": "9d2dc06b-f31d-41cf-8e5c-66be8d90eac9",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[1, 1],\n",
       "       [1, 1]])"
      ]
     },
     "execution_count": 21,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "ones([2,2], dtype = int)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "51728595-c497-4189-8738-34ff68ae1426",
   "metadata": {
    "tags": []
   },
   "source": [
    "## numpy.zeros_like\n",
    "\n",
    "> numpy.zeros_like 用于创建一个与给定数组具有相同形状的数组，数组元素以 0 来填充。\n",
    "\n",
    "`numpy.zeros_like(a, dtype=None, order='K', subok=True, shape=None)`\n",
    "\n",
    "参数|描述\n",
    "--:|:--\n",
    "a|给定要创建相同形状的数组\n",
    "dtype|创建的数组的数据类型\n",
    "order|数组在内存中的存储顺序，可选值为 'C'（按行优先）或 'F'（按列优先），默认为 'K'（保留输入数组的存储顺序）\n",
    "subok|是否允许返回子类，如果为 True，则返回一个子类对象，否则返回一个与 a 数组具有相同数据类型和存储顺序的数组\n",
    "shape|创建的数组的形状，如果不指定，则默认为 a 数组的形状。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "id": "277eea4c-7fbf-4ce0-a3b0-2ee4d6ac093b",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[0, 0, 0],\n",
       "       [0, 0, 0],\n",
       "       [0, 0, 0]])"
      ]
     },
     "execution_count": 22,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "zeros_like(array([[1, 2, 3], [4, 5, 6], [7, 8, 9]]))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0ccf6bfa-fd83-4467-8413-51a35e28dff5",
   "metadata": {},
   "source": [
    "## numpy.ones_like\n",
    "\n",
    "> numpy.ones_like 用于创建一个与给定数组具有相同形状的数组，数组元素以 1 来填充。\n",
    "\n",
    "`numpy.ones_like(a, dtype=None, order='K', subok=True, shape=None)`\n",
    "\n",
    "参数|描述\n",
    "--:|:--\n",
    "a|给定要创建相同形状的数组\n",
    "dtype|创建的数组的数据类型\n",
    "order|数组在内存中的存储顺序，可选值为 'C'（按行优先）或 'F'（按列优先），默认为 'K'（保留输入数组的存储顺序）\n",
    "subok|是否允许返回子类，如果为 True，则返回一个子类对象，否则返回一个与 a 数组具有相同数据类型和存储顺序的数组\n",
    "shape|创建的数组的形状，如果不指定，则默认为 a 数组的形状。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "id": "f85b525c-27b4-4c8c-8e5a-ce8c136d1c83",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[1, 1, 1],\n",
       "       [1, 1, 1],\n",
       "       [1, 1, 1]])"
      ]
     },
     "execution_count": 23,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "ones_like(array([[1, 2, 3], [4, 5, 6], [7, 8, 9]]))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "30472531-8c5c-4d91-b8db-683e81b816f1",
   "metadata": {
    "tags": []
   },
   "source": [
    "# 从已有的数组创建数组"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a70540e7-753f-47c5-9f02-333ae6b0ceb5",
   "metadata": {},
   "source": [
    "## numpy.asarray\n",
    "\n",
    "`numpy.asarray(a, dtype = None, order = None)`\n",
    "\n",
    "参数|描述\n",
    "--:|:--\n",
    "a|任意形式的输入参数，可以是，列表, 列表的元组, 元组, 元组的元组, 元组的列表，多维数组\n",
    "dtype|数据类型，可选\n",
    "order|可选，有\"C\"和\"F\"两个选项,分别代表，行优先和列优先，在计算机内存中的存储元素的顺序。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "id": "252fa8c0-1480-4917-8414-24b6915c5abd",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([1, 2, 3])"
      ]
     },
     "execution_count": 24,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "asarray([1,2,3]) "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "id": "ae50a5e3-f031-490a-a790-de5d42f125a5",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([1, 2, 3])"
      ]
     },
     "execution_count": 25,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "asarray((1,2,3)) "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "id": "486dc043-7e68-4569-807c-7b3a7e6b708c",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([1., 2., 3.])"
      ]
     },
     "execution_count": 26,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "asarray([1,2,3], dtype=float)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c04a068c-dece-4a9d-80b2-2db28dff4d5d",
   "metadata": {},
   "source": [
    "## numpy.frombuffer\n",
    "\n",
    "> numpy.frombuffer 用于实现动态数组。\n",
    "\n",
    "> numpy.frombuffer 接受 buffer 输入参数，以流的形式读入转化成 ndarray 对象。\n",
    "\n",
    "`numpy.frombuffer(buffer, dtype = float, count = -1, offset = 0)`\n",
    "\n",
    "> 注意：buffer 是字符串的时候，Python3 默认 str 是 Unicode 类型，所以要转成 bytestring 在原 str 前加上 b。\n",
    "\n",
    "参数|描述\n",
    "--:|:--\n",
    "buffer|可以是任意对象，会以流的形式读入。\n",
    "dtype|返回数组的数据类型，可选\n",
    "count|读取的数据数量，默认为-1，读取所有数据。\n",
    "offset|读取的起始位置，默认为0。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "id": "c674c37c-27ba-4c96-a606-7ca8f541572a",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([b'H', b'e', b'l', b'l', b'o', b' ', b'W', b'o', b'r', b'l', b'd'],\n",
       "      dtype='|S1')"
      ]
     },
     "execution_count": 27,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "frombuffer(b'Hello World', dtype='S1')"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0b44f29e-bb34-4fba-b23c-26a0e69ec92d",
   "metadata": {},
   "source": [
    "## numpy.fromiter\n",
    "\n",
    "> numpy.fromiter 方法从可迭代对象中建立 ndarray 对象，返回一维数组。\n",
    "\n",
    "`numpy.fromiter(iterable, dtype, count=-1)`\n",
    "\n",
    "参数|描述\n",
    "--:|:--\n",
    "iterable|可迭代对象\n",
    "dtype|返回数组的数据类型\n",
    "count|读取的数据数量，默认为-1，读取所有数据"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "id": "c65923c5-a12c-4d93-b6eb-ec802fc8b934",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([0., 1., 2., 3., 4.])"
      ]
     },
     "execution_count": 28,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "fromiter(iter(range(5)), dtype=float)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4b3dbc98-97f4-4f46-8b25-a6a42d6256be",
   "metadata": {},
   "source": [
    "# 从数值范围创建数组"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "40577d85-c1e2-4f56-9997-50334e81ab61",
   "metadata": {
    "tags": []
   },
   "source": [
    "## numpy.arange\n",
    "\n",
    "> numpy 包中的使用 arange 函数创建数值范围并返回 ndarray 对象\n",
    "\n",
    "`numpy.arange(start, stop, step, dtype)`\n",
    "\n",
    "> 根据 start 与 stop 指定的范围以及 step 设定的步长，生成一个 ndarray。\n",
    "\n",
    "参数|描述\n",
    "--:|:--\n",
    "start|起始值，默认为0\n",
    "stop|终止值（不包含）\n",
    "step|步长，默认为1\n",
    "dtype|返回ndarray的数据类型，如果没有提供，则会使用输入数据的类型。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "id": "6c13f74c-95b6-4999-94ed-361fbbbbb005",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([0, 1, 2, 3, 4])"
      ]
     },
     "execution_count": 29,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arange(5)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "id": "1eef30ea-5781-4cda-8cba-519079fc3ce4",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([0., 1., 2., 3., 4.])"
      ]
     },
     "execution_count": 30,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arange(5, dtype=float)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "id": "b9bd5433-3f0c-4ec2-ad48-27759f4fbd73",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([10, 12, 14, 16, 18])"
      ]
     },
     "execution_count": 31,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arange(10,20,2)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "452ff6b5-6dff-4641-a43a-6a9704c06092",
   "metadata": {},
   "source": [
    "## numpy.linspace\n",
    "\n",
    "> numpy.linspace 函数用于创建一个一维数组，数组是一个等差数列构成的，格式如下：\n",
    "\n",
    "`np.linspace(start, stop, num=50, endpoint=True, retstep=False, dtype=None)`\n",
    "\n",
    "参数|描述\n",
    "--:|:--\n",
    "start|序列的起始值\n",
    "stop|序列的终止值，如果endpoint为true，该值包含于数列中\n",
    "num|要生成的等步长的样本数量，默认为50\n",
    "endpoint|该值为 true 时，数列中包含stop值，反之不包含，默认是True。\n",
    "retstep|如果为 True 时，生成的数组中会显示间距，反之不显示。\n",
    "dtype|ndarray 的数据类型"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "id": "94a87291-3895-4b6e-a8ce-4cacb45bf446",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([ 1.,  2.,  3.,  4.,  5.,  6.,  7.,  8.,  9., 10.])"
      ]
     },
     "execution_count": 32,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "linspace(1,10,10)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "id": "2b66ae86-451c-481c-bc59-2dcc75b20b42",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([1., 1., 1., 1., 1., 1., 1., 1., 1., 1.])"
      ]
     },
     "execution_count": 33,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "linspace(1,1,10)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "id": "d4fa2c02-74df-4270-940b-9c77d181fb00",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([10., 12., 14., 16., 18.])"
      ]
     },
     "execution_count": 34,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "linspace(10, 20,  5, endpoint=False)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "id": "aae96279-d6b9-496d-9ae5-e3d9438a74a3",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(array([ 1.,  2.,  3.,  4.,  5.,  6.,  7.,  8.,  9., 10.]), 1.0)"
      ]
     },
     "execution_count": 35,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "linspace(1,10,10,retstep=True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "id": "a2ffd0ec-2cc5-4fc5-812a-f4f5fe55c699",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 1.],\n",
       "       [ 2.],\n",
       "       [ 3.],\n",
       "       [ 4.],\n",
       "       [ 5.],\n",
       "       [ 6.],\n",
       "       [ 7.],\n",
       "       [ 8.],\n",
       "       [ 9.],\n",
       "       [10.]])"
      ]
     },
     "execution_count": 36,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "linspace(1,10,10).reshape([10,1])"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b0542d6a-6efe-480c-86f0-f60b5b1556e8",
   "metadata": {},
   "source": [
    "## numpy.logspace\n",
    "\n",
    "> numpy.logspace 函数用于创建一个于等比数列。格式如下：\n",
    "\n",
    "`np.logspace(start, stop, num=50, endpoint=True, base=10.0, dtype=None)`\n",
    "\n",
    "参数|描述\n",
    "--:|:--\n",
    "start|序列的起始值为：base ** start\n",
    "stop|序列的终止值为：base ** stop。如果endpoint为true，该值包含于数列中\n",
    "num|要生成的等步长的样本数量，默认为50\n",
    "endpoint|该值为 true 时，数列中中包含stop值，反之不包含，默认是True。\n",
    "base|对数 log 的底数。\n",
    "dtype|ndarray 的数据类型"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 37,
   "id": "f586e6c7-d8bf-490c-ba36-ac39824d8705",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([ 10.        ,  12.91549665,  16.68100537,  21.5443469 ,\n",
       "        27.82559402,  35.93813664,  46.41588834,  59.94842503,\n",
       "        77.42636827, 100.        ])"
      ]
     },
     "execution_count": 37,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "logspace(1.0,  2.0, num=10)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "id": "b8ac0779-206f-48f0-98f7-8a0c5c7cccab",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([  1.,   2.,   4.,   8.,  16.,  32.,  64., 128., 256., 512.])"
      ]
     },
     "execution_count": 38,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "logspace(0,9,10,base=2)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "79c5e704-8cbb-4e02-9aa9-cb415f8fd11a",
   "metadata": {},
   "source": [
    "# 切片和索引"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 39,
   "id": "a1fb7fbc-8d8d-4f86-8200-c9d27ebd32f6",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([2, 4, 6])"
      ]
     },
     "execution_count": 39,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a = arange(10)\n",
    "s = slice(2,7,2)\n",
    "a[s]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 40,
   "id": "d2b11a7c-f840-48de-ad40-644185362744",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([2, 4, 6])"
      ]
     },
     "execution_count": 40,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arange(10)[2:7:2]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 41,
   "id": "06387986-cc17-4ec0-97d7-495c8cc0fdc1",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "5"
      ]
     },
     "execution_count": 41,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arange(10)[5]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 42,
   "id": "82fde833-49b1-46e1-a345-dacad2087e56",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([2, 3, 4, 5, 6, 7, 8, 9])"
      ]
     },
     "execution_count": 42,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arange(10)[2:]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 43,
   "id": "3b48f8c0-d5e1-469a-8262-4ba52f516261",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([2, 3, 4])"
      ]
     },
     "execution_count": 43,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arange(10)[2:5]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 44,
   "id": "af2d5726-10c5-4977-ae63-aa921589dc93",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[3, 4, 5],\n",
       "       [4, 5, 6]])"
      ]
     },
     "execution_count": 44,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "array([[1,2,3],[3,4,5],[4,5,6]])[1:]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 45,
   "id": "f66960c3-0d91-4f12-bf2f-7b0702d8b091",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([2, 4, 5])"
      ]
     },
     "execution_count": 45,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "array([[1,2,3],[3,4,5],[4,5,6]])[...,1]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 46,
   "id": "9d5cf8a9-e84d-4077-988a-dcd5e96e0265",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([3, 4, 5])"
      ]
     },
     "execution_count": 46,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "array([[1,2,3],[3,4,5],[4,5,6]])[1,...]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 47,
   "id": "2faa12e8-6fb9-4eb8-85c0-9f06981e7280",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[2, 3],\n",
       "       [4, 5],\n",
       "       [5, 6]])"
      ]
     },
     "execution_count": 47,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "array([[1,2,3],[3,4,5],[4,5,6]])[...,1:]"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "232a0243-72b0-44fa-aaad-90d9099b3526",
   "metadata": {},
   "source": [
    "# 高级索引"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e9352ac2-3577-4f32-9aa6-fcaa9b1946e7",
   "metadata": {},
   "source": [
    "## 整数数组索引"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 48,
   "id": "13177665-3e45-4a72-a556-c5e77ec07cad",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([1, 4, 5])"
      ]
     },
     "execution_count": 48,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "array([[1,  2],  [3,  4],  [5,  6]])[[0,1,2],  [0,1,0]]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 49,
   "id": "f2a70ea3-d570-4486-96d8-3afed98e1a31",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 0,  2],\n",
       "       [ 9, 11]])"
      ]
     },
     "execution_count": 49,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "x = array([[  0,  1,  2],[  3,  4,  5],[  6,  7,  8],[  9,  10,  11]])\n",
    "rows = array([[0,0],[3,3]]) \n",
    "cols = array([[0,2],[0,2]]) \n",
    "x[rows,cols]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 50,
   "id": "7747bad0-04c7-4fa1-af99-67f7dd0a589e",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[5, 6],\n",
       "       [8, 9]])"
      ]
     },
     "execution_count": 50,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "array([[1,2,3], [4,5,6],[7,8,9]])[1:3, 1:3]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 51,
   "id": "8fa90bd5-ec8d-4c82-a9a1-3b327ca0d099",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[5, 6],\n",
       "       [8, 9]])"
      ]
     },
     "execution_count": 51,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "array([[1,2,3], [4,5,6],[7,8,9]])[1:3,[1,2]]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 52,
   "id": "26f20956-50a8-456d-b7cc-3b65ab8ea2c3",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[2, 3],\n",
       "       [5, 6],\n",
       "       [8, 9]])"
      ]
     },
     "execution_count": 52,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "array([[1,2,3], [4,5,6],[7,8,9]])[...,1:]"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "12e96471-a98c-4647-b363-cd5962a14370",
   "metadata": {},
   "source": [
    "## 布尔索引"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 53,
   "id": "3dfb2b6a-6608-41c4-9851-4a572ba96da8",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([ 6,  7,  8,  9, 10, 11])"
      ]
     },
     "execution_count": 53,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "x = array([[  0,  1,  2],[  3,  4,  5],[  6,  7,  8],[  9,  10,  11]])  \n",
    "x[x>5]"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3cc1f527-8eda-4800-a262-1496d4b43f66",
   "metadata": {},
   "source": [
    "> 以下实例使用了 ~（取补运算符）来过滤 NaN。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 54,
   "id": "2645a061-87d7-48bd-bc82-d77072f61d8d",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[1. 2. 3. 4. 5.]\n"
     ]
    }
   ],
   "source": [
    "a = np.array([np.nan,  1,2,np.nan,3,4,5])\n",
    "print (a[~np.isnan(a)])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 55,
   "id": "3b2af5aa-35a5-4309-b7e8-3d3261f98e00",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[2. +6.j 3.5+5.j]\n"
     ]
    }
   ],
   "source": [
    "a = np.array([1,  2+6j,  5,  3.5+5j])\n",
    "print (a[np.iscomplex(a)])"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ec4aeed9-5ea7-4ec3-b095-ab1a076c9f63",
   "metadata": {},
   "source": [
    "## 花式索引\n",
    "\n",
    "### 一维数组"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 56,
   "id": "9f89d2e1-8b94-4e74-bcf5-c7797cd4b475",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([0, 6])"
      ]
     },
     "execution_count": 56,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "x = np.arange(9)\n",
    "x2 = x[[0, 6]]\n",
    "x2"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 57,
   "id": "d31ab18f-f33f-4c92-a7ff-234311741b95",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0"
      ]
     },
     "execution_count": 57,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "x2[0]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 58,
   "id": "3791a728-e1d4-4b69-bc81-a90e98459f4e",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "6"
      ]
     },
     "execution_count": 58,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "x2[1]"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "aae39d53-d0e5-4b84-b2a9-3cb74fdae370",
   "metadata": {},
   "source": [
    "### 二维数组"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 59,
   "id": "9b67b1ac-2365-4463-833d-bd94751e8edf",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[16, 17, 18, 19],\n",
       "       [ 8,  9, 10, 11],\n",
       "       [ 4,  5,  6,  7],\n",
       "       [28, 29, 30, 31]])"
      ]
     },
     "execution_count": 59,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arange(32).reshape((8,4))[[4,2,1,7]]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 60,
   "id": "229054ac-858d-454c-8205-50e7d42de2f3",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[16, 17, 18, 19],\n",
       "       [24, 25, 26, 27],\n",
       "       [28, 29, 30, 31],\n",
       "       [ 4,  5,  6,  7]])"
      ]
     },
     "execution_count": 60,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arange(32).reshape((8,4))[[-4,-2,-1,-7]]"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "87896e08-7262-48d0-8d18-f804f0386948",
   "metadata": {},
   "source": [
    "> np.ix_ 函数就是输入两个数组，产生笛卡尔积的映射关系。\n",
    "\n",
    "> 笛卡尔乘积是指在数学中，两个集合 X 和 Y 的笛卡尔积（Cartesian product），又称直积，表示为 X×Y，第一个对象是X的成员而第二个对象是 Y 的所有可能有序对的其中一个成员。\n",
    "\n",
    "> 例如 A={a,b}, B={0,1,2}，则：\n",
    "\n",
    "> A×B={(a, 0), (a, 1), (a, 2), (b, 0), (b, 1), (b, 2)}\n",
    "> B×A={(0, a), (0, b), (1, a), (1, b), (2, a), (2, b)}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 61,
   "id": "915c2c5e-5742-4a05-a360-96be53a24cf0",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 4,  7,  5,  6],\n",
       "       [20, 23, 21, 22],\n",
       "       [28, 31, 29, 30],\n",
       "       [ 8, 11,  9, 10]])"
      ]
     },
     "execution_count": 61,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arange(32).reshape((8,4))[np.ix_([1,5,7,2],[0,3,1,2])]"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3e84fb30-8075-4de9-95d9-0a9231050a5f",
   "metadata": {},
   "source": [
    "# 广播(Broadcast)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 62,
   "id": "6146ee31-f981-4ccb-bcf0-443de29e41e0",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([ 10,  40,  90, 160])"
      ]
     },
     "execution_count": 62,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "array([1,2,3,4]) * array([10,20,30,40])"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ce8a5803-9a2d-4271-a2d4-900c8d39b2c1",
   "metadata": {},
   "source": [
    "> 当运算中的 2 个数组的形状不同时，numpy 将自动触发广播机制。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 63,
   "id": "e3f2cbe1-f04d-4179-bb29-a51eb3de44dd",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 0,  1,  2],\n",
       "       [10, 11, 12],\n",
       "       [20, 21, 22],\n",
       "       [30, 31, 32]])"
      ]
     },
     "execution_count": 63,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "array([[ 0, 0, 0],[10,10,10],[20,20,20],[30,30,30]]) + array([0,1,2])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 64,
   "id": "2679a2a3-1d54-4b65-8c79-a2366b842f65",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[ 1  2  3]\n",
      " [11 12 13]\n",
      " [21 22 23]\n",
      " [31 32 33]]\n"
     ]
    }
   ],
   "source": [
    "a = array([[ 0, 0, 0],\n",
    "           [10,10,10],\n",
    "           [20,20,20],\n",
    "           [30,30,30]])\n",
    "b = array([1,2,3])\n",
    "bb = tile(b, (4, 1))\n",
    "print(a + bb)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d2aee280-a2ed-42d7-b65c-fb09ded6d045",
   "metadata": {},
   "source": [
    "# 迭代数组"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 65,
   "id": "51f15200-ea69-4a00-b77f-05b87e88ac8f",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0, 1, 2, 3, 4, 5, "
     ]
    }
   ],
   "source": [
    "for x in nditer(arange(6).reshape(2,3)):\n",
    "    print (x, end=\", \")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 66,
   "id": "16d80962-c261-44c6-b689-4f960c198187",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0, 1, 2, 3, 4, 5, "
     ]
    }
   ],
   "source": [
    "a = arange(6).reshape(2,3)\n",
    "for x in nditer(a.T):\n",
    "    print (x, end=\", \")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 67,
   "id": "8808c6f6-db3f-4c69-a62b-8a8c285e750b",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0, 3, 1, 4, 2, 5, "
     ]
    }
   ],
   "source": [
    "for x in nditer(a.T.copy(order='C')):\n",
    "    print (x, end=\", \")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 68,
   "id": "45b3cec3-c30c-4910-9e96-0d3d78cb18a1",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 0,  5, 10, 15],\n",
       "       [20, 25, 30, 35],\n",
       "       [40, 45, 50, 55]])"
      ]
     },
     "execution_count": 68,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a = np.arange(0,60,5)\n",
    "a = a.reshape(3,4)\n",
    "a"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 69,
   "id": "863a00d0-818e-4237-9356-d424da12864a",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 0, 20, 40],\n",
       "       [ 5, 25, 45],\n",
       "       [10, 30, 50],\n",
       "       [15, 35, 55]])"
      ]
     },
     "execution_count": 69,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "b = a.T\n",
    "b"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 70,
   "id": "2fc35427-88e1-4e95-b42e-5cc9230eda84",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 0, 20, 40],\n",
       "       [ 5, 25, 45],\n",
       "       [10, 30, 50],\n",
       "       [15, 35, 55]])"
      ]
     },
     "execution_count": 70,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "c = b.copy(order='C')\n",
    "c"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 71,
   "id": "11653889-4a10-47bf-835e-0cc89d4fb3a7",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0, 20, 40, 5, 25, 45, 10, 30, 50, 15, 35, 55, "
     ]
    }
   ],
   "source": [
    "for x in np.nditer(c):\n",
    "    print (x, end=\", \" )"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 72,
   "id": "fcf4e6a2-90e7-4e36-b119-4382f7a1c371",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 0, 20, 40],\n",
       "       [ 5, 25, 45],\n",
       "       [10, 30, 50],\n",
       "       [15, 35, 55]])"
      ]
     },
     "execution_count": 72,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "c = b.copy(order='F')\n",
    "c"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 73,
   "id": "5741b12c-a6f6-43de-a09b-180321a0ec70",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, "
     ]
    }
   ],
   "source": [
    "for x in np.nditer(c):\n",
    "    print (x, end=\", \" )"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 74,
   "id": "ae7912c1-15f1-4694-963c-ab6b49c9d9cd",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 0,  5, 10, 15],\n",
       "       [20, 25, 30, 35],\n",
       "       [40, 45, 50, 55]])"
      ]
     },
     "execution_count": 74,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a = np.arange(0,60,5).reshape(3,4)\n",
    "a"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 75,
   "id": "b2338085-6c74-4abb-82dc-3f4efa3292d3",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[  0,  10,  20,  30],\n",
       "       [ 40,  50,  60,  70],\n",
       "       [ 80,  90, 100, 110]])"
      ]
     },
     "execution_count": 75,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "for x in np.nditer(a, op_flags=['readwrite']):\n",
    "    x[...]=2*x\n",
    "a"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4821a5b0-8a50-4ad9-808b-a00d2580ad52",
   "metadata": {},
   "source": [
    "## 使用外部循环\n",
    "\n",
    "> nditer 类的构造器拥有 flags 参数，它可以接受下列值：\n",
    "\n",
    "参数|描述\n",
    "--:|:--\n",
    "c_index|可以跟踪 C 顺序的索引\n",
    "f_index|可以跟踪 Fortran 顺序的索引\n",
    "multi_index|每次迭代可以跟踪一种索引类型\n",
    "external_loop|给出的值是具有多个值的一维数组，而不是零维数组"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 76,
   "id": "af5f8539-c474-4491-a75c-1ca4fb0d5433",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 0,  5, 10, 15],\n",
       "       [20, 25, 30, 35],\n",
       "       [40, 45, 50, 55]])"
      ]
     },
     "execution_count": 76,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a = arange(0,60,5).reshape(3,4)\n",
    "a"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 77,
   "id": "189ed17a-f308-46e9-8d04-43efc7425601",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[ 0 20 40], [ 5 25 45], [10 30 50], [15 35 55], "
     ]
    }
   ],
   "source": [
    "for x in np.nditer(a, flags=['external_loop'], order='F'):\n",
    "    print (x, end=\", \")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c223add7-67c5-4502-8e0c-22c4165f2a56",
   "metadata": {},
   "source": [
    "## 广播迭代"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 78,
   "id": "79c13044-bd78-4fdc-a714-ad15e3bed09b",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 0,  5, 10, 15],\n",
       "       [20, 25, 30, 35],\n",
       "       [40, 45, 50, 55]])"
      ]
     },
     "execution_count": 78,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a = np.arange(0,60,5).reshape(3,4)\n",
    "a"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 79,
   "id": "34d2d66e-8e3e-49b8-9485-3f9558cc995a",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([1, 2, 3, 4])"
      ]
     },
     "execution_count": 79,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "b = np.array([1,  2,  3,  4], dtype=int)\n",
    "b"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 80,
   "id": "aebd6f34-b7c9-4212-9650-5a8b2c9aa29b",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0:1, 5:2, 10:3, 15:4, 20:1, 25:2, 30:3, 35:4, 40:1, 45:2, 50:3, 55:4, "
     ]
    }
   ],
   "source": [
    "for x,y in np.nditer([a,b]):\n",
    "    print (\"%d:%d\"  %  (x,y), end=\", \")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8383d5cf-d8d5-4f09-9125-932030df4d2f",
   "metadata": {},
   "source": [
    "# 数组操作"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "31f10bb4-7563-4787-8b56-f2a452d3cfaa",
   "metadata": {},
   "source": [
    "## 修改数组形状\n",
    "\n",
    "函数|描述\n",
    "--:|:--\n",
    "reshape|不改变数据的条件下修改形状\n",
    "flat|数组元素迭代器\n",
    "flatten|返回一份数组拷贝，对拷贝所做的修改不会影响原始数组\n",
    "ravel|返回展开数组"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "174f1887-77ca-4a96-8388-3fbb8bc8d060",
   "metadata": {},
   "source": [
    "### numpy.reshape\n",
    "\n",
    "> numpy.reshape 函数可以在不改变数据的条件下修改形状，格式如下：\n",
    "\n",
    "`numpy.reshape(arr, newshape, order='C')`\n",
    "\n",
    "> arr：要修改形状的数组\n",
    "\n",
    "> newshape：整数或者整数数组，新的形状应当兼容原有形状\n",
    "\n",
    "> order：'C' -- 按行，'F' -- 按列，'A' -- 原顺序，'k' -- 元素在内存中的出现顺序。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 81,
   "id": "cbd63747-6c5f-411f-a7d4-1ecdc1d620a8",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[0, 1],\n",
       "       [2, 3],\n",
       "       [4, 5],\n",
       "       [6, 7]])"
      ]
     },
     "execution_count": 81,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arange(8).reshape(4,2)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "27fac7a0-bd5d-427c-8eba-3bcac8f2de26",
   "metadata": {},
   "source": [
    "### numpy.ndarray.flat\n",
    "\n",
    "> numpy.ndarray.flat 是一个数组元素迭代器"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 82,
   "id": "0764c8c4-c3fd-4058-9891-2ae7bcfcd295",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0\n",
      "1\n",
      "2\n",
      "3\n",
      "4\n",
      "5\n",
      "6\n",
      "7\n",
      "8\n"
     ]
    }
   ],
   "source": [
    "for element in arange(9).reshape(3,3).flat:\n",
    "    print (element)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "fccfa442-82ef-4a8c-b7b9-74d2005fe871",
   "metadata": {},
   "source": [
    "### numpy.ndarray.flatten\n",
    "\n",
    "> numpy.ndarray.flatten 返回一份数组拷贝，对拷贝所做的修改不会影响原始数组，格式如下：\n",
    "\n",
    "`ndarray.flatten(order='C')`\n",
    "\n",
    "> order：'C' -- 按行，'F' -- 按列，'A' -- 原顺序，'K' -- 元素在内存中的出现顺序。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 83,
   "id": "46a87619-2517-4e8c-9d30-80a6ab519da1",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([0, 1, 2, 3, 4, 5, 6, 7])"
      ]
     },
     "execution_count": 83,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arange(8).reshape(2,4).flatten()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 84,
   "id": "99fc290f-699d-4e5c-bb9f-4630d60dfe1e",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([0, 4, 1, 5, 2, 6, 3, 7])"
      ]
     },
     "execution_count": 84,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arange(8).reshape(2,4).flatten(order='F')"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "632221f5-f5c8-4643-bf84-f165722eade4",
   "metadata": {},
   "source": [
    "### numpy.ravel\n",
    "\n",
    "> numpy.ravel() 展平的数组元素，顺序通常是\"C风格\"，返回的是数组视图（view，有点类似 C/C++引用reference的意味），修改会影响原始数组。\n",
    "\n",
    "`numpy.ravel(a, order='C')`\n",
    "\n",
    "> order：'C' -- 按行，'F' -- 按列，'A' -- 原顺序，'K' -- 元素在内存中的出现顺序。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 85,
   "id": "cce557ef-4469-4487-90e5-f25fb2ff59ff",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[0, 1, 2, 3],\n",
       "       [4, 5, 6, 7]])"
      ]
     },
     "execution_count": 85,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a = np.arange(8).reshape(2,4)\n",
    "a"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 86,
   "id": "d2cdc1b1-35e6-48ff-80d5-0dc999a4ff4e",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([0, 1, 2, 3, 4, 5, 6, 7])"
      ]
     },
     "execution_count": 86,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a.ravel()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 87,
   "id": "2f8f45b5-7ef1-46ae-8e1a-bfe7bbaebb2a",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([0, 4, 1, 5, 2, 6, 3, 7])"
      ]
     },
     "execution_count": 87,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a.ravel(order = 'F')"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0ddaaf4e-8403-43b9-8c3a-5842250dfcb9",
   "metadata": {},
   "source": [
    "## 翻转数组\n",
    "\n",
    "函数|描述\n",
    "--:|:--\n",
    "transpose|对换数组的维度\n",
    "ndarray.T|和 self.transpose() 相同\n",
    "rollaxis|向后滚动指定的轴\n",
    "swapaxes|对换数组的两个轴"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d5bb7c3d-abaa-4ea2-b2e0-2e15dcfc704d",
   "metadata": {},
   "source": [
    "### numpy.transpose\n",
    "\n",
    "> numpy.transpose 函数用于对换数组的维度\n",
    "\n",
    "`numpy.transpose(arr, axes)`\n",
    "\n",
    "> arr：要操作的数组\n",
    "\n",
    "> axes：整数列表，对应维度，通常所有维度都会对换。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 88,
   "id": "13175621-f52c-4490-b98b-37672a0c1206",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 0,  1,  2,  3],\n",
       "       [ 4,  5,  6,  7],\n",
       "       [ 8,  9, 10, 11]])"
      ]
     },
     "execution_count": 88,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a = arange(12).reshape(3,4)\n",
    "a"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 89,
   "id": "2931b435-20c0-4f79-8c32-ccf61d148bb8",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 0,  4,  8],\n",
       "       [ 1,  5,  9],\n",
       "       [ 2,  6, 10],\n",
       "       [ 3,  7, 11]])"
      ]
     },
     "execution_count": 89,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "transpose(a)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "19a53708-cb15-473b-8ec8-cc5fec12592a",
   "metadata": {},
   "source": [
    "> numpy.ndarray.T 类似 numpy.transpose"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 90,
   "id": "2850ec13-74c3-44c9-ac19-2ccdc95face5",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 0,  4,  8],\n",
       "       [ 1,  5,  9],\n",
       "       [ 2,  6, 10],\n",
       "       [ 3,  7, 11]])"
      ]
     },
     "execution_count": 90,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a.T"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "38d96019-0a34-45c0-ad08-4d85745f9d67",
   "metadata": {
    "tags": []
   },
   "source": [
    "### numpy.rollaxis\n",
    "\n",
    "> numpy.rollaxis 函数向后滚动特定的轴到一个特定位置\n",
    "\n",
    "`numpy.rollaxis(arr, axis, start)`\n",
    "\n",
    "> arr：数组\n",
    "> axis：要向后滚动的轴，其它轴的相对位置不会改变\n",
    "> start：默认为零，表示完整的滚动。会滚动到特定位置。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 91,
   "id": "146da567-00d2-4ef1-8874-0e427f784f76",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[[0, 1],\n",
       "        [2, 3]],\n",
       "\n",
       "       [[4, 5],\n",
       "        [6, 7]]])"
      ]
     },
     "execution_count": 91,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a = arange(8).reshape(2,2,2)\n",
    "a"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 92,
   "id": "31915e15-a4ae-4460-9862-a04e444696ad",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(array([1]), array([1]), array([0]))"
      ]
     },
     "execution_count": 92,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "where(a==6)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 93,
   "id": "fa7c4af5-b5de-44c7-8a1e-fb07f39eda91",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "6"
      ]
     },
     "execution_count": 93,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a[1,1,0]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 94,
   "id": "db6b1612-b125-4efd-b4b9-745b6fdb7d10",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[[0, 2],\n",
       "        [4, 6]],\n",
       "\n",
       "       [[1, 3],\n",
       "        [5, 7]]])"
      ]
     },
     "execution_count": 94,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "b = rollaxis(a,2,0)\n",
    "b"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 95,
   "id": "c6784fba-8bf1-4fa2-a7c6-6bb5cb45a92f",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(array([0]), array([1]), array([1]))"
      ]
     },
     "execution_count": 95,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "where(b==6)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 96,
   "id": "800ef9e2-c0b4-4d02-97c2-3b2c09c31891",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[[0, 2],\n",
       "        [1, 3]],\n",
       "\n",
       "       [[4, 6],\n",
       "        [5, 7]]])"
      ]
     },
     "execution_count": 96,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "c = np.rollaxis(a,2,1)\n",
    "c"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 97,
   "id": "d562bf68-8ca8-47d1-82d4-4c83a7faa8a8",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(array([1]), array([0]), array([1]))"
      ]
     },
     "execution_count": 97,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "where(c==6)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "602beede-926d-43d1-82c0-6f2f06c9f92a",
   "metadata": {},
   "source": [
    "### numpy.swapaxes\n",
    "\n",
    "> numpy.swapaxes 函数用于交换数组的两个轴\n",
    "\n",
    "`numpy.swapaxes(arr, axis1, axis2)`\n",
    "\n",
    "> arr：输入的数组\n",
    "\n",
    "> axis1：对应第一个轴的整数\n",
    "\n",
    "> axis2：对应第二个轴的整数"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 98,
   "id": "87555567-e441-4222-9ed5-3070f2765077",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[[0, 1],\n",
       "        [2, 3]],\n",
       "\n",
       "       [[4, 5],\n",
       "        [6, 7]]])"
      ]
     },
     "execution_count": 98,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 99,
   "id": "514043ee-5203-4d3b-99ed-f026e201d220",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[[0, 4],\n",
       "        [2, 6]],\n",
       "\n",
       "       [[1, 5],\n",
       "        [3, 7]]])"
      ]
     },
     "execution_count": 99,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "swapaxes(a, 2, 0)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "afb52c94-bde8-480b-b1b1-dfa5619d8c0e",
   "metadata": {},
   "source": [
    "## 修改数组维度\n",
    "\n",
    "维度|描述\n",
    "--:|:--\n",
    "broadcast|产生模仿广播的对象\n",
    "broadcast_to|将数组广播到新形状\n",
    "expand_dims|扩展数组的形状\n",
    "squeeze|从数组的形状中删除一维条目"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2ecc3321-c43d-482c-896f-39aaae997f45",
   "metadata": {},
   "source": [
    "### numpy.broadcast\n",
    "\n",
    "> numpy.broadcast 用于模仿广播的对象，它返回一个对象，该对象封装了将一个数组广播到另一个数组的结果。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 100,
   "id": "e39e1602-6898-494d-b0d0-e17cc710a407",
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "x = array([[1], [2], [3]])\n",
    "y = array([4, 5, 6])\n",
    "b = broadcast(x,y)\n",
    "r,c = b.iters"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 101,
   "id": "194d9e97-2c23-422c-9748-da479844dd36",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1 4\n"
     ]
    }
   ],
   "source": [
    "print (next(r), next(c))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 102,
   "id": "baaf7ec1-98da-4e4f-83e3-1535d4167b74",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1 5\n"
     ]
    }
   ],
   "source": [
    "print (next(r), next(c))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 103,
   "id": "d3020572-0dcb-44f9-a3af-c2e2f1de6a2c",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(3, 3)"
      ]
     },
     "execution_count": 103,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "b.shape"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 104,
   "id": "0d4bf002-4cb7-4476-beec-82b630434b8b",
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "b = broadcast(x,y)\n",
    "c = empty(b.shape)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 105,
   "id": "47ae72bb-baaf-4fc0-bf62-6bfd550e3803",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(3, 3)"
      ]
     },
     "execution_count": 105,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "c.shape"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 106,
   "id": "cae308ed-e466-4cc7-ad43-b21062d2834f",
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "c.flat = [u + v for (u,v) in b]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 107,
   "id": "1f41fa6f-6449-43e4-ac08-7b9916697734",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[5., 6., 7.],\n",
       "       [6., 7., 8.],\n",
       "       [7., 8., 9.]])"
      ]
     },
     "execution_count": 107,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "c"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 108,
   "id": "be0e1df0-34c2-4931-a84e-6abfb7d1f379",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[5, 6, 7],\n",
       "       [6, 7, 8],\n",
       "       [7, 8, 9]])"
      ]
     },
     "execution_count": 108,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "x + y"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1e3969a6-704a-4e9a-8891-31904e3ac3e1",
   "metadata": {},
   "source": [
    "### numpy.broadcast_to\n",
    "\n",
    "> numpy.broadcast_to 函数将数组广播到新形状。它在原始数组上返回只读视图。 它通常不连续。 如果新形状不符合 NumPy 的广播规则，该函数可能会抛出ValueError。\n",
    "\n",
    "`numpy.broadcast_to(array, shape, subok)`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 109,
   "id": "4ddd7e3a-4cad-4979-8431-df89e4724e52",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[0, 1, 2, 3]])"
      ]
     },
     "execution_count": 109,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a = np.arange(4).reshape(1,4)\n",
    "a"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 110,
   "id": "797104f1-8b0f-43d8-b366-f467c44b3a18",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[0, 1, 2, 3],\n",
       "       [0, 1, 2, 3],\n",
       "       [0, 1, 2, 3],\n",
       "       [0, 1, 2, 3]])"
      ]
     },
     "execution_count": 110,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "broadcast_to(a,(4,4))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "091a4164-8be1-4165-8037-f87a10d0cb9f",
   "metadata": {},
   "source": [
    "### numpy.expand_dims\n",
    "\n",
    "> numpy.expand_dims 函数通过在指定位置插入新的轴来扩展数组形状，函数格式如下:\n",
    "\n",
    "`numpy.expand_dims(arr, axis)`\n",
    "\n",
    "> arr：输入数组\n",
    "\n",
    "> axis：新轴插入的位置"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 111,
   "id": "9e41e257-9fa9-4547-9037-a0f90ca306cc",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[1, 2],\n",
       "       [3, 4]])"
      ]
     },
     "execution_count": 111,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "x = np.array(([1,2],[3,4]))\n",
    "x"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 112,
   "id": "1c97ff5a-21df-42e9-b26b-a02ae7db3b14",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[[1, 2],\n",
       "        [3, 4]]])"
      ]
     },
     "execution_count": 112,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "y = np.expand_dims(x, axis = 0)\n",
    "y"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 113,
   "id": "56e6dbea-36cc-46ae-a68d-d35956998f70",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "((2, 2), (1, 2, 2))"
      ]
     },
     "execution_count": 113,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "x.shape, y.shape"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 114,
   "id": "45429dc4-b802-46c6-b775-5b585cc3b542",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[[1, 2]],\n",
       "\n",
       "       [[3, 4]]])"
      ]
     },
     "execution_count": 114,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "y = np.expand_dims(x, axis = 1)\n",
    "y"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 115,
   "id": "e5a12150-9c34-401c-8f63-cc18ea424ef2",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(2, 3)"
      ]
     },
     "execution_count": 115,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "x.ndim,y.ndim"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 116,
   "id": "7d717bcf-2ba2-4a2a-b094-b76a31d4b0fa",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "((2, 2), (2, 1, 2))"
      ]
     },
     "execution_count": 116,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "x.shape, y.shape"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a10ee0ae-a3be-4cad-b923-24b0326809d3",
   "metadata": {},
   "source": [
    "### numpy.squeeze\n",
    "\n",
    "> numpy.squeeze 函数从给定数组的形状中删除一维的条目，函数格式如下：\n",
    "\n",
    "`numpy.squeeze(arr, axis)`\n",
    "\n",
    "> arr：输入数组\n",
    "\n",
    "> axis：整数或整数元组，用于选择形状中一维条目的子集"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 117,
   "id": "5434d47c-fa7f-436b-9641-fc74bc7ae4cc",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[[0, 1, 2],\n",
       "        [3, 4, 5],\n",
       "        [6, 7, 8]]])"
      ]
     },
     "execution_count": 117,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "x = arange(9).reshape(1,3,3)\n",
    "x"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 118,
   "id": "8e57a5fa-c7a6-4a19-ab7b-88994d3d37eb",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[0, 1, 2],\n",
       "       [3, 4, 5],\n",
       "       [6, 7, 8]])"
      ]
     },
     "execution_count": 118,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "y = squeeze(x)\n",
    "y"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 119,
   "id": "3db7b4a7-078e-4e59-80b7-232c781fce43",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "((1, 3, 3), (3, 3))"
      ]
     },
     "execution_count": 119,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "x.shape, y.shape"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "edd7957f-4b9d-4ec6-b476-d0dc542f8692",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "ad2c6e0e-a95c-4b1e-9811-0b00cd0110a9",
   "metadata": {},
   "source": [
    "## 连接数组\n",
    "\n",
    "函数|描述\n",
    "--:|:--\n",
    "concatenate|连接沿现有轴的数组序列\n",
    "stack|沿着新的轴加入一系列数组。\n",
    "hstack|水平堆叠序列中的数组（列方向）\n",
    "vstack|竖直堆叠序列中的数组（行方向）"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "eaaa2651-306e-4c34-8638-dc60a835289b",
   "metadata": {},
   "source": [
    "### numpy.concatenate\n",
    "\n",
    "> numpy.concatenate 函数用于沿指定轴连接相同形状的两个或多个数组，格式如下：\n",
    "\n",
    "`numpy.concatenate((a1, a2, ...), axis)`\n",
    "\n",
    "> a1, a2, ...：相同类型的数组\n",
    "\n",
    "> axis：沿着它连接数组的轴，默认为 0"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 120,
   "id": "85f4c096-f76f-4db1-ac4c-62f583085cca",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(array([[1, 2],\n",
       "        [3, 4]]),\n",
       " array([[5, 6],\n",
       "        [7, 8]]))"
      ]
     },
     "execution_count": 120,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a = array([[1,2],[3,4]])\n",
    "b = array([[5,6],[7,8]])\n",
    "a, b"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 121,
   "id": "f7ec8206-996c-41ac-8154-ed9d0b54757b",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[1, 2],\n",
       "       [3, 4],\n",
       "       [5, 6],\n",
       "       [7, 8]])"
      ]
     },
     "execution_count": 121,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "concatenate((a,b))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 122,
   "id": "b5773931-4282-4405-af8d-86c2d1164805",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[1, 2, 5, 6],\n",
       "       [3, 4, 7, 8]])"
      ]
     },
     "execution_count": 122,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "concatenate((a,b),axis = 1)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4255fc9f-12c7-45b1-be90-a8fa2a2c5d61",
   "metadata": {},
   "source": [
    "### numpy.stack\n",
    "\n",
    "> numpy.stack 函数用于沿新轴连接数组序列，格式如下：\n",
    "\n",
    "`numpy.stack(arrays, axis)`\n",
    "\n",
    "> arrays相同形状的数组序列\n",
    "\n",
    "> axis：返回数组中的轴，输入数组沿着它来堆叠"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 123,
   "id": "6a2272bc-0653-46ea-af1a-f8ea4b9991b8",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(array([[1, 2],\n",
       "        [3, 4]]),\n",
       " array([[5, 6],\n",
       "        [7, 8]]))"
      ]
     },
     "execution_count": 123,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a = array([[1,2],[3,4]])\n",
    "b = array([[5,6],[7,8]])\n",
    "a, b"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 124,
   "id": "fe6c38b2-6f3a-4434-a321-3c2da2888b52",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[[1, 2],\n",
       "        [3, 4]],\n",
       "\n",
       "       [[5, 6],\n",
       "        [7, 8]]])"
      ]
     },
     "execution_count": 124,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "stack((a,b),0)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 125,
   "id": "ecf2c8ad-ad6c-47df-8828-001e12464584",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[[1, 2],\n",
       "        [5, 6]],\n",
       "\n",
       "       [[3, 4],\n",
       "        [7, 8]]])"
      ]
     },
     "execution_count": 125,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "stack((a,b),1)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b3eadb14-738f-4a21-a026-56f09cd7d468",
   "metadata": {},
   "source": [
    "### numpy.hstack\n",
    "\n",
    "> numpy.hstack 是 numpy.stack 函数的变体，它通过水平堆叠来生成数组。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 126,
   "id": "0ce9eb08-8c62-4436-b159-cf68bf1c6be4",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(array([[1, 2],\n",
       "        [3, 4]]),\n",
       " array([[5, 6],\n",
       "        [7, 8]]))"
      ]
     },
     "execution_count": 126,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a = array([[1,2],[3,4]])\n",
    "b = array([[5,6],[7,8]])\n",
    "a, b"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 127,
   "id": "f965198c-3039-4ca6-8bda-6f0c436824c5",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[1, 2, 5, 6],\n",
       "       [3, 4, 7, 8]])"
      ]
     },
     "execution_count": 127,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "hstack((a,b))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "227674f7-13de-4580-9e66-47c653f0b842",
   "metadata": {},
   "source": [
    "### numpy.vstack\n",
    "\n",
    "> numpy.vstack 是 numpy.stack 函数的变体，它通过垂直堆叠来生成数组。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 128,
   "id": "2ceb08ea-49ae-4ee6-beb6-0adbb5a3dd13",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(array([[1, 2],\n",
       "        [3, 4]]),\n",
       " array([[5, 6],\n",
       "        [7, 8]]))"
      ]
     },
     "execution_count": 128,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a = array([[1,2],[3,4]])\n",
    "b = array([[5,6],[7,8]])\n",
    "a, b"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 129,
   "id": "c9d08115-72a6-4426-a85d-67229b80a060",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[1, 2],\n",
       "       [3, 4],\n",
       "       [5, 6],\n",
       "       [7, 8]])"
      ]
     },
     "execution_count": 129,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "vstack((a,b))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0335e894-288a-4f90-b347-5f8e90bdaf09",
   "metadata": {},
   "source": [
    "## 分割数组\n",
    "\n",
    "函数|数组及操作\n",
    "--:|:--\n",
    "split|将一个数组分割为多个子数组\n",
    "hsplit|将一个数组水平分割为多个子数组（按列）\n",
    "vsplit|将一个数组垂直分割为多个子数组（按行）"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b6af3d1f-ebc8-42ce-9453-2af2a09a24d6",
   "metadata": {},
   "source": [
    "### numpy.split\n",
    "\n",
    "> numpy.split 函数沿特定的轴将数组分割为子数组\n",
    "\n",
    "`numpy.split(ary, indices_or_sections, axis)`\n",
    "\n",
    "> ary：被分割的数组\n",
    "\n",
    "> indices_or_sections：如果是一个整数，就用该数平均切分，如果是一个数组，为沿轴切分的位置（左开右闭）\n",
    "\n",
    "> axis：设置沿着哪个方向进行切分，默认为 0，横向切分，即水平方向。为 1 时，纵向切分，即竖直方向。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 130,
   "id": "fb478b95-02b7-4985-8889-d69d7247dfbc",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[array([0, 1, 2]), array([3, 4, 5]), array([6, 7, 8])]"
      ]
     },
     "execution_count": 130,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a = arange(9)\n",
    "split(a,3)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 131,
   "id": "447b24ce-d5ce-4a1a-9cc3-482e02004fa8",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[array([0, 1, 2, 3]), array([4, 5, 6]), array([7, 8])]"
      ]
     },
     "execution_count": 131,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "split(a,[4,7])"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5db78ede-c10d-4ff7-9a3b-cde81c97899c",
   "metadata": {},
   "source": [
    "> axis 为 0 时在水平方向分割，axis 为 1 时在垂直方向分割"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 132,
   "id": "361b1315-1096-414e-ab4a-6f03b34f7937",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 0,  1,  2,  3],\n",
       "       [ 4,  5,  6,  7],\n",
       "       [ 8,  9, 10, 11],\n",
       "       [12, 13, 14, 15]])"
      ]
     },
     "execution_count": 132,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a = arange(16).reshape(4, 4)\n",
    "a"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 133,
   "id": "c912c418-15f5-4146-8f33-4d7997af5e9b",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[array([[0, 1, 2, 3],\n",
       "        [4, 5, 6, 7]]),\n",
       " array([[ 8,  9, 10, 11],\n",
       "        [12, 13, 14, 15]])]"
      ]
     },
     "execution_count": 133,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "split(a,2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 134,
   "id": "ba39b6a3-4756-4102-a770-e20e9f5c3306",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[array([[ 0,  1],\n",
       "        [ 4,  5],\n",
       "        [ 8,  9],\n",
       "        [12, 13]]),\n",
       " array([[ 2,  3],\n",
       "        [ 6,  7],\n",
       "        [10, 11],\n",
       "        [14, 15]])]"
      ]
     },
     "execution_count": 134,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "split(a,2,1)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "75668aa3-6b69-4b38-a276-60fe8b1d0b5d",
   "metadata": {},
   "source": [
    "### numpy.hsplit\n",
    "\n",
    "> numpy.hsplit 函数用于水平分割数组，通过指定要返回的相同形状的数组数量来拆分原数组。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 135,
   "id": "9200da0c-13a4-4b92-a44e-eccb7716fae3",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[2., 8., 3., 8., 5., 1.],\n",
       "       [7., 0., 5., 6., 5., 1.]])"
      ]
     },
     "execution_count": 135,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a = floor(10 * random.random((2, 6)))\n",
    "a"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 136,
   "id": "cba716ee-8609-4148-acf8-2878196b24d6",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[array([[2., 8.],\n",
       "        [7., 0.]]),\n",
       " array([[3., 8.],\n",
       "        [5., 6.]]),\n",
       " array([[5., 1.],\n",
       "        [5., 1.]])]"
      ]
     },
     "execution_count": 136,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "hsplit(a, 3)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f8e9afdc-3b65-4a86-9dd3-1b14fc746bfa",
   "metadata": {},
   "source": [
    "### numpy.vsplit\n",
    "\n",
    "> numpy.vsplit 沿着垂直轴分割，其分割方式与hsplit用法相同。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 137,
   "id": "3f83d434-1749-4e61-9afc-0c5a1e882699",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 0,  1,  2,  3],\n",
       "       [ 4,  5,  6,  7],\n",
       "       [ 8,  9, 10, 11],\n",
       "       [12, 13, 14, 15]])"
      ]
     },
     "execution_count": 137,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a = np.arange(16).reshape(4,4)\n",
    "a"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 138,
   "id": "b93b2838-bbfe-4566-abce-ca1ff065c1f7",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[array([[0, 1, 2, 3],\n",
       "        [4, 5, 6, 7]]),\n",
       " array([[ 8,  9, 10, 11],\n",
       "        [12, 13, 14, 15]])]"
      ]
     },
     "execution_count": 138,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "vsplit(a,2)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0e610102-0cf5-4764-a989-b6dc95ddc362",
   "metadata": {},
   "source": [
    "## 数组元素的添加与删除\n",
    "\n",
    "函数|元素及描述\n",
    "--:|:--\n",
    "resize|返回指定形状的新数组\n",
    "append|将值添加到数组末尾\n",
    "insert|沿指定轴将值插入到指定下标之前\n",
    "delete|删掉某个轴的子数组，并返回删除后的新数组\n",
    "unique|查找数组内的唯一元素"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "613c6adc-7c44-4794-8864-8daacb2dbb56",
   "metadata": {},
   "source": [
    "### numpy.resize\n",
    "\n",
    "> numpy.resize 函数返回指定大小的新数组。如果新数组大小大于原始大小，则包含原始数组中的元素的副本。\n",
    "\n",
    "`numpy.resize(arr, shape)`\n",
    "\n",
    "> arr：要修改大小的数组\n",
    "> shape：返回数组的新形状"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 139,
   "id": "41bd9a30-ccf0-4eb9-b99a-75ded918952a",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(array([[1, 2, 3],\n",
       "        [4, 5, 6]]),\n",
       " (2, 3))"
      ]
     },
     "execution_count": 139,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a = array([[1,2,3],[4,5,6]])\n",
    "a, a.shape"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 140,
   "id": "2555ddba-1508-4bbe-b6d2-3a58fb2fa988",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[1, 2],\n",
       "       [3, 4],\n",
       "       [5, 6]])"
      ]
     },
     "execution_count": 140,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "resize(a, (3,2))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 141,
   "id": "7b44a805-3765-47dd-8371-b51199cbf368",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[1, 2, 3],\n",
       "       [4, 5, 6],\n",
       "       [1, 2, 3]])"
      ]
     },
     "execution_count": 141,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "resize(a,(3,3))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "73f1b4ca-b14b-4c79-87e5-f8a29210349e",
   "metadata": {},
   "source": [
    "### numpy.append\n",
    "\n",
    "> numpy.append 函数在数组的末尾添加值。\n",
    "\n",
    "> 追加操作会分配整个数组，并把原来的数组复制到新数组中。 \n",
    "\n",
    "> 此外，输入数组的维度必须匹配否则将生成ValueError。\n",
    "\n",
    "> append 函数返回的始终是一个一维数组。\n",
    "\n",
    "`numpy.append(arr, values, axis=None)`\n",
    "\n",
    "> arr：输入数组\n",
    "\n",
    "> values：要向arr添加的值，需要和arr形状相同（除了要添加的轴）\n",
    "\n",
    "> axis：默认为 None。当axis无定义时，是横向加成，返回总是为一维数组！\n",
    "\n",
    "> 当axis有定义的时候，分别为0和1的时候。\n",
    "\n",
    "> 当axis有定义的时候，分别为0和1的时候（列数要相同）。\n",
    "\n",
    "> 当axis为1时，数组是加在右边（行数要相同）。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 142,
   "id": "e4264d64-28e8-4192-8e3e-a30b8552c6ad",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[1, 2, 3],\n",
       "       [4, 5, 6]])"
      ]
     },
     "execution_count": 142,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a = array([[1,2,3],[4,5,6]])\n",
    "a"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 143,
   "id": "183cfe5b-0e9c-4b89-83b1-040ad0af1d69",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([1, 2, 3, 4, 5, 6, 7, 8, 9])"
      ]
     },
     "execution_count": 143,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "append(a, [7,8,9])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 144,
   "id": "ea5ba57c-1ab2-4c41-9911-2bbde1e06957",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[1, 2, 3],\n",
       "       [4, 5, 6],\n",
       "       [7, 8, 9]])"
      ]
     },
     "execution_count": 144,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "append(a, [[7,8,9]],axis = 0)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 145,
   "id": "dfe78ae6-3088-47ff-96f2-655d247d9b38",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[1, 2, 3, 5, 5, 5],\n",
       "       [4, 5, 6, 7, 8, 9]])"
      ]
     },
     "execution_count": 145,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "append(a, [[5,5,5],[7,8,9]],axis = 1)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "bbf82965-8f4e-4d77-8218-e08a8b355938",
   "metadata": {},
   "source": [
    "### numpy.insert\n",
    "\n",
    "> numpy.insert 函数在给定索引之前，沿给定轴在输入数组中插入值。\n",
    "\n",
    "> 如果值的类型转换为要插入，则它与输入数组不同。\n",
    "\n",
    "> 插入没有原地的，函数会返回一个新数组。\n",
    "\n",
    "> 此外，如果未提供轴，则输入数组会被展开。\n",
    "\n",
    "`numpy.insert(arr, obj, values, axis)`\n",
    "\n",
    "> arr：输入数组\n",
    "\n",
    "> obj：在其之前插入值的索引\n",
    "\n",
    "> values：要插入的值\n",
    "\n",
    "> axis：沿着它插入的轴，如果未提供，则输入数组会被展开"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 146,
   "id": "b927948a-f20e-46a7-991b-0280814f9e76",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[1, 2],\n",
       "       [3, 4],\n",
       "       [5, 6]])"
      ]
     },
     "execution_count": 146,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a = array([[1,2],[3,4],[5,6]])\n",
    "a"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 147,
   "id": "694beff8-2cbb-4431-bd95-ef74c337c209",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([ 1,  2,  3, 11, 12,  4,  5,  6])"
      ]
     },
     "execution_count": 147,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "insert(a,3,[11,12])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 148,
   "id": "c4274665-4e9d-4255-b32f-d61554107d91",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 1,  2],\n",
       "       [11, 11],\n",
       "       [ 3,  4],\n",
       "       [ 5,  6]])"
      ]
     },
     "execution_count": 148,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "insert(a,1,[11],axis = 0)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 149,
   "id": "2ea097c2-0e4b-492d-baca-069ed02a1114",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 1, 11,  2],\n",
       "       [ 3, 11,  4],\n",
       "       [ 5, 11,  6]])"
      ]
     },
     "execution_count": 149,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "insert(a,1,11,axis = 1)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "869437ae-27ce-4f90-bed8-287e1f35b26a",
   "metadata": {},
   "source": [
    "### numpy.delete\n",
    "\n",
    "> numpy.delete 函数返回从输入数组中删除指定子数组的新数组。 与 insert() 函数的情况一样，如果未提供轴参数，则输入数组将展开。\n",
    "\n",
    "`Numpy.delete(arr, obj, axis)`\n",
    "\n",
    "> arr：输入数组\n",
    "\n",
    "> obj：可以被切片，整数或者整数数组，表明要从输入数组删除的子数组\n",
    "\n",
    "> axis：沿着它删除给定子数组的轴，如果未提供，则输入数组会被展开"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 150,
   "id": "9e8608b3-6d98-4923-be80-c358918da9b1",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 0,  1,  2,  3],\n",
       "       [ 4,  5,  6,  7],\n",
       "       [ 8,  9, 10, 11]])"
      ]
     },
     "execution_count": 150,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a = arange(12).reshape(3,4)\n",
    "a"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 151,
   "id": "482bc7d1-7096-4811-9a92-d56ea835ff5a",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([ 0,  1,  2,  3,  4,  6,  7,  8,  9, 10, 11])"
      ]
     },
     "execution_count": 151,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "delete(a,5)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 152,
   "id": "bdbb2621-ecb1-4645-91ea-824b5c589d9f",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 0,  2,  3],\n",
       "       [ 4,  6,  7],\n",
       "       [ 8, 10, 11]])"
      ]
     },
     "execution_count": 152,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "delete(a,1,axis = 1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 153,
   "id": "ceaab4ba-a012-4c66-a53c-04bb021442d0",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([ 2,  4,  6,  8, 10])"
      ]
     },
     "execution_count": 153,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a = np.array([1,2,3,4,5,6,7,8,9,10])\n",
    "delete(a, s_[::2])"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1fb84d1a-9991-4e79-ac71-15743e24642d",
   "metadata": {},
   "source": [
    "### numpy.unique\n",
    "\n",
    "> numpy.unique 函数用于去除数组中的重复元素。\n",
    "\n",
    "`numpy.unique(arr, return_index, return_inverse, return_counts)`\n",
    "\n",
    "> arr：输入数组，如果不是一维数组则会展开\n",
    "\n",
    "> return_index：如果为true，返回新列表元素在旧列表中的位置（下标），并以列表形式储\n",
    "\n",
    "> return_inverse：如果为true，返回旧列表元素在新列表中的位置（下标），并以列表形式储\n",
    "\n",
    "> return_counts：如果为true，返回去重数组中的元素在原数组中的出现次数"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 154,
   "id": "1472c0dd-6050-41df-b923-d304c769869a",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(array([5, 2, 6, 2, 7, 5, 6, 8, 2, 9]), array([2, 5, 6, 7, 8, 9]))"
      ]
     },
     "execution_count": 154,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a = array([5,2,6,2,7,5,6,8,2,9])\n",
    "a, unique(a)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 155,
   "id": "34735c44-8933-4318-bd76-ba9d01f7e400",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([1, 0, 2, 4, 7, 9])"
      ]
     },
     "execution_count": 155,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "u,indices = unique(a, return_index = True)\n",
    "indices"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 156,
   "id": "6c26f38d-d240-4ba1-b1e6-b57e470a302c",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(array([2, 5, 6, 7, 8, 9]), array([1, 0, 2, 0, 3, 1, 2, 4, 0, 5]))"
      ]
     },
     "execution_count": 156,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "u,indices = unique(a,return_inverse = True)\n",
    "u, indices"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 157,
   "id": "76051467-513f-4a13-9e50-80306f64c0de",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([5, 2, 6, 2, 7, 5, 6, 8, 2, 9])"
      ]
     },
     "execution_count": 157,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "u[indices]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 158,
   "id": "107af08d-4f6e-4eec-b719-b6cee134a36a",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(array([2, 5, 6, 7, 8, 9]), array([3, 2, 2, 1, 1, 1]))"
      ]
     },
     "execution_count": 158,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "u,indices = unique(a,return_counts = True)\n",
    "u, indices"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f4d61be9-0e9a-4686-bfd2-f82c7d35432d",
   "metadata": {},
   "source": [
    "# 位运算\n",
    "\n",
    "函数|描述\n",
    "--:|:--\n",
    "bitwise_and|对数组元素执行位与操作\n",
    "bitwise_or|对数组元素执行位或操作\n",
    "invert|按位取反\n",
    "left_shift|向左移动二进制表示的位\n",
    "right_shift|向右移动二进制表示的位\n",
    "\n",
    "> 注：也可以使用 \"&\"、 \"~\"、 \"|\" 和 \"^\" 等操作符进行计算。"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6482e2f4-2779-4ecd-bfad-fb56e3c36430",
   "metadata": {
    "slideshow": {
     "slide_type": "notes"
    },
    "tags": []
   },
   "source": [
    "## bitwise_and\n",
    "\n",
    "> bitwise_and() 函数对数组中整数的二进制形式执行位与运算。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 159,
   "id": "5d03969e-bbb3-4974-9a60-a56a43815281",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "('0b1101', '0b10001')"
      ]
     },
     "execution_count": 159,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a,b = 13,17\n",
    "bin(a), bin(b)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 160,
   "id": "ec086f80-0bff-4705-9ba6-2555efe8f412",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "1"
      ]
     },
     "execution_count": 160,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "bitwise_and(13, 17)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "964d05b4-d5a6-45b8-8039-522304a08793",
   "metadata": {},
   "source": [
    "## bitwise_or\n",
    "\n",
    "> bitwise_or()函数对数组中整数的二进制形式执行位或运算。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 161,
   "id": "e4bc04a2-bfb1-44c8-80de-afda3daf6ce3",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "('0b1101', '0b10001')"
      ]
     },
     "execution_count": 161,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a,b = 13,17\n",
    "bin(a), bin(b)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 162,
   "id": "af645690-4e3c-4e07-bb69-60e70252f233",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "29"
      ]
     },
     "execution_count": 162,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "bitwise_or(13, 17)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3969b682-f6aa-421c-a702-fa1bbe7cf631",
   "metadata": {},
   "source": [
    "## invert\n",
    "\n",
    "> invert() 函数对数组中整数进行位取反运算，即 0 变成 1，1 变成 0。\n",
    "\n",
    "> 对于有符号整数，取该二进制数的补码，然后 +1。二进制数，最高位为0表示正数，最高位为 1 表示负数。\n",
    "\n",
    "> 看看 ~1 的计算步骤：\n",
    "\n",
    "*    将1(这里叫：原码)转二进制 ＝ 00000001\n",
    "\n",
    "*    按位取反 ＝ 11111110\n",
    "\n",
    "*    发现符号位(即最高位)为1(表示负数)，将除符号位之外的其他数字取反 ＝ 10000001\n",
    "\n",
    "*    末位加1取其补码 ＝ 10000010\n",
    "\n",
    "*    转换回十进制 ＝ -2"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 163,
   "id": "525567f3-0e3d-4960-97db-c4357948fff7",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([242], dtype=uint8)"
      ]
     },
     "execution_count": 163,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "invert(array([13], dtype = uint8))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 164,
   "id": "4e55b6f8-d3aa-4546-bbdd-e46c4ef682b1",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'00001101'"
      ]
     },
     "execution_count": 164,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "binary_repr(13, width = 8)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 165,
   "id": "68669e2d-8b58-430a-83df-0311f0f840ac",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'11110010'"
      ]
     },
     "execution_count": 165,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "binary_repr(242, width = 8)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d2851b25-19a9-4772-a271-2884935cd529",
   "metadata": {},
   "source": [
    "## left_shift\n",
    "\n",
    "> left_shift() 函数将数组元素的二进制形式向左移动到指定位置，右侧附加相等数量的 0。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 166,
   "id": "cf41b485-e121-4fba-bad0-e782913ca1d7",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "40"
      ]
     },
     "execution_count": 166,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "left_shift(10,2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 167,
   "id": "8113e3dd-0380-4563-98e4-849982ff1659",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'00001010'"
      ]
     },
     "execution_count": 167,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "binary_repr(10, width = 8)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 168,
   "id": "e431911c-5926-4ece-b0dc-05e93062f99c",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'00101000'"
      ]
     },
     "execution_count": 168,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "binary_repr(40, width = 8)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "cf21b39c-94cb-4e5e-bbec-75a99e68dd71",
   "metadata": {},
   "source": [
    "## right_shift\n",
    "\n",
    "> right_shift() 函数将数组元素的二进制形式向右移动到指定位置，左侧附加相等数量的 0。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 169,
   "id": "ab6b0117-943b-49b7-8f8d-353f6e1d7b87",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "10"
      ]
     },
     "execution_count": 169,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "right_shift(40,2)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e9b3cde8-cf1c-4b0e-a02a-cf4876837695",
   "metadata": {},
   "source": [
    "# 字符串函数\n",
    "\n",
    "函数|描述\n",
    "--:|:--\n",
    "add()|对两个数组的逐个字符串元素进行连接\n",
    "multiply()|返回按元素多重连接后的字符串\n",
    "center()|居中字符串\n",
    "capitalize()|将字符串第一个字母转换为大写\n",
    "title()|将字符串的每个单词的第一个字母转换为大写\n",
    "lower()|数组元素转换为小写\n",
    "upper()|数组元素转换为大写\n",
    "split()|指定分隔符对字符串进行分割，并返回数组列表\n",
    "splitlines()|返回元素中的行列表，以换行符分割\n",
    "strip()|移除元素开头或者结尾处的特定字符\n",
    "join()|通过指定分隔符来连接数组中的元素\n",
    "replace()|使用新字符串替换字符串中的所有子字符串\n",
    "decode()|数组元素依次调用str.decode\n",
    "encode()|数组元素依次调用str.encode"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "287cd08d-de7d-4711-b90f-19317bc6a382",
   "metadata": {
    "tags": []
   },
   "source": [
    "## numpy.char.add()\n",
    "\n",
    "> numpy.char.add() 函数依次对两个数组的元素进行字符串连接。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 170,
   "id": "36a9605d-0f88-438f-bd71-5df20f68db5f",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array(['hello xyz'], dtype='<U9')"
      ]
     },
     "execution_count": 170,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "char.add(['hello'],[' xyz'])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 171,
   "id": "17a8b769-927f-4556-b4b3-d3a31aec01b0",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array(['hello abc', 'hi xyz'], dtype='<U9')"
      ]
     },
     "execution_count": 171,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "char.add(['hello', 'hi'],[' abc', ' xyz'])"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "164a439e-f08a-4569-8b53-c4264a67067f",
   "metadata": {},
   "source": [
    "## numpy.char.multiply()\n",
    "\n",
    "> numpy.char.multiply() 函数执行多重连接。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 172,
   "id": "85d60f88-7ff7-4ff9-b3a6-9ae6102cdd1c",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array('Runoob Runoob Runoob ', dtype='<U21')"
      ]
     },
     "execution_count": 172,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "char.multiply('Runoob ',3)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d465c74c-d629-4fc1-ab94-7343ea68ebb8",
   "metadata": {},
   "source": [
    "## numpy.char.center()\n",
    "\n",
    "> numpy.char.center() 函数用于将字符串居中，并使用指定字符在左侧和右侧进行填充。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 173,
   "id": "16dc275e-57aa-4aaf-a27f-d6aa8792e9db",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array('*******Runoob*******', dtype='<U20')"
      ]
     },
     "execution_count": 173,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "char.center('Runoob', 20,fillchar = '*')"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "90b435ea-c199-4fd3-9b99-3fecae81faf9",
   "metadata": {},
   "source": [
    "## numpy.char.capitalize()\n",
    "\n",
    "> numpy.char.capitalize() 函数将字符串的第一个字母转换为大写"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 174,
   "id": "5eedd828-88a2-46d5-a88b-a3facc2591bf",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array('Runoob', dtype='<U6')"
      ]
     },
     "execution_count": 174,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "char.capitalize('runoob')"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e2e465c8-30e3-4b33-9811-bb86d4e7de44",
   "metadata": {},
   "source": [
    "## numpy.char.title()\n",
    "\n",
    "> numpy.char.title() 函数将字符串的每个单词的第一个字母转换为大写"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 175,
   "id": "770777e6-0b4e-452c-a7e6-88a2847d56ba",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array('I Like Runoob', dtype='<U13')"
      ]
     },
     "execution_count": 175,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "char.title('i like runoob')"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ba68754b-90d5-4186-a6b5-6882c8f45b6f",
   "metadata": {},
   "source": [
    "## numpy.char.lower()\n",
    "\n",
    "> numpy.char.lower() 函数对数组的每个元素转换为小写。它对每个元素调用 str.lower。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 176,
   "id": "b071cd5a-7da9-4b7b-b9d4-d5cd89f30beb",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array(['runoob', 'google'], dtype='<U6')"
      ]
     },
     "execution_count": 176,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "char.lower(['RUNOOB','GOOGLE'])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 177,
   "id": "e173e2af-373e-4336-b44a-dec5ba8b4ddb",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array('runoob', dtype='<U6')"
      ]
     },
     "execution_count": 177,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "char.lower('RUNOOB')"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e92f911f-6a80-4281-9d86-6aa64dcfacaa",
   "metadata": {},
   "source": [
    "## numpy.char.upper()\n",
    "\n",
    "> numpy.char.upper() 函数对数组的每个元素转换为大写。它对每个元素调用 str.upper。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 178,
   "id": "6a2f1f49-507a-4203-9c5a-cc3adb5ecba2",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array(['RUNOOB', 'GOOGLE'], dtype='<U6')"
      ]
     },
     "execution_count": 178,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "char.upper(['runoob','google'])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 179,
   "id": "a9e43ffe-7ae1-44de-ad33-c761d22548f9",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array('RUNOOB', dtype='<U6')"
      ]
     },
     "execution_count": 179,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "char.upper('runoob')"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "aa4a09b8-e153-4897-beb1-9f6ef7f9a07f",
   "metadata": {},
   "source": [
    "## numpy.char.split()\n",
    "\n",
    "> numpy.char.split() 通过指定分隔符对字符串进行分割，并返回数组。默认情况下，分隔符为空格。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 180,
   "id": "bd443a2b-95da-45dc-844d-ba1add28cd3e",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array(list(['i', 'like', 'runoob?']), dtype=object)"
      ]
     },
     "execution_count": 180,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "char.split ('i like runoob?')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 181,
   "id": "a6b32457-ec6f-4aae-9f03-6bd4daa0ad2f",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array(list(['www', 'runoob', 'com']), dtype=object)"
      ]
     },
     "execution_count": 181,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "char.split ('www.runoob.com', sep = '.')"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "205de495-c23d-4417-bd80-37cfdb47b614",
   "metadata": {},
   "source": [
    "## numpy.char.splitlines()\n",
    "\n",
    "> numpy.char.splitlines() 函数以换行符作为分隔符来分割字符串，并返回数组。\\n，\\r，\\r\\n 都可用作换行符。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 182,
   "id": "b443d26b-f7ae-4e58-9899-8843e6f8cf86",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array(list(['i', 'like runoob?']), dtype=object)"
      ]
     },
     "execution_count": 182,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "char.splitlines('i\\nlike runoob?')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 183,
   "id": "67aa5cce-9391-48a5-afea-8f255699fc3d",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array(list(['i', 'like runoob?']), dtype=object)"
      ]
     },
     "execution_count": 183,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "char.splitlines('i\\rlike runoob?')"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7baac3ca-b9ea-4f2d-acfa-2ca735793653",
   "metadata": {},
   "source": [
    "## numpy.char.strip()\n",
    "\n",
    "> numpy.char.strip() 函数用于移除开头或结尾处的特定字符。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 184,
   "id": "f089381c-c3c9-4e05-b96b-fc93b8490367",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array('shok arunoob', dtype='<U14')"
      ]
     },
     "execution_count": 184,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "char.strip('ashok arunooba','a')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 185,
   "id": "49fa21f8-2fda-460e-88c0-68367d6f1d9a",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array(['runoob', 'dmin', 'jav'], dtype='<U8')"
      ]
     },
     "execution_count": 185,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "char.strip(['arunooba','admin','java'],'a')"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6b4a9bbe-aa87-40fb-91d8-5ca8bcebda4d",
   "metadata": {},
   "source": [
    "## numpy.char.join()\n",
    "\n",
    "> numpy.char.join() 函数通过指定分隔符来连接数组中的元素或字符串"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 186,
   "id": "8baf8d28-8fc0-4298-9e6f-6fd8007b9411",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array('r:u:n:o:o:b', dtype='<U11')"
      ]
     },
     "execution_count": 186,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "char.join(':','runoob')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 187,
   "id": "dfedac4e-ec35-4495-a964-fb467433ffac",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array(['r:u:n:o:o:b', 'g-o-o-g-l-e'], dtype='<U11')"
      ]
     },
     "execution_count": 187,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "char.join([':','-'],['runoob','google'])"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "620e2379-35a5-46c0-939e-a235685982c3",
   "metadata": {},
   "source": [
    "## numpy.char.replace()\n",
    "\n",
    "> numpy.char.replace() 函数使用新字符串替换字符串中的所有子字符串。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 188,
   "id": "43d6b789-ba78-444e-bcc3-17d819187402",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array('i like runccb', dtype='<U13')"
      ]
     },
     "execution_count": 188,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "char.replace ('i like runoob', 'oo', 'cc')"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "84135fdd-7430-4718-9867-be06d409cce2",
   "metadata": {
    "tags": []
   },
   "source": [
    "## numpy.char.encode()\n",
    "\n",
    "> numpy.char.encode() 函数对数组中的每个元素调用 str.encode 函数。\n",
    "\n",
    "> 默认编码是 utf-8，可以使用标准 Python 库中的编解码器。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 189,
   "id": "8718208a-7518-48e2-8e38-20597020ea34",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array(b'\\x99\\xa4\\x95\\x96\\x96\\x82', dtype='|S6')"
      ]
     },
     "execution_count": 189,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "char.encode('runoob', 'cp500')"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7eac6250-ac99-43ab-84cd-7b612f55a80b",
   "metadata": {},
   "source": [
    "## numpy.char.decode()\n",
    "\n",
    "> numpy.char.decode() 函数对编码的元素进行 str.decode() 解码。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 190,
   "id": "39c17b76-f330-4cef-965b-d1d1f77c2017",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "b'\\x99\\xa4\\x95\\x96\\x96\\x82'\n",
      "runoob\n"
     ]
    }
   ],
   "source": [
    "a = np.char.encode('runoob', 'cp500') \n",
    "print (a)\n",
    "print (np.char.decode(a,'cp500'))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "37e59020-1796-46d0-a941-d52c918b02ba",
   "metadata": {},
   "source": [
    "# 数学函数"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "70b9104f-658d-4213-80f6-95f84c68c965",
   "metadata": {},
   "source": [
    "## 三角函数\n",
    "\n",
    "> NumPy 提供了标准的三角函数：sin()、cos()、tan()。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 191,
   "id": "b5d95706-a237-45af-a610-1dbd296484d7",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([0.        , 0.5       , 0.70710678, 0.8660254 , 1.        ])"
      ]
     },
     "execution_count": 191,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a = np.array([0,30,45,60,90])\n",
    "np.sin(a*np.pi/180)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 192,
   "id": "89e9af49-f60b-453a-9364-fbb22b33e7b6",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([1.00000000e+00, 8.66025404e-01, 7.07106781e-01, 5.00000000e-01,\n",
       "       6.12323400e-17])"
      ]
     },
     "execution_count": 192,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.cos(a*np.pi/180)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 193,
   "id": "53082b07-3dff-4f34-b90f-5460a7f2016a",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([0.00000000e+00, 5.77350269e-01, 1.00000000e+00, 1.73205081e+00,\n",
       "       1.63312394e+16])"
      ]
     },
     "execution_count": 193,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.tan(a*np.pi/180)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4125f47f-72d4-4762-a6bf-8884336077fd",
   "metadata": {},
   "source": [
    "> arcsin，arccos，和 arctan 函数返回给定角度的 sin，cos 和 tan 的反三角函数。\n",
    "\n",
    "> 这些函数的结果可以通过 numpy.degrees() 函数将弧度转换为角度。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 194,
   "id": "25568a74-21e4-4f46-bccf-ddb2aed6dd16",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[ 0. 30. 45. 60. 90.]\n"
     ]
    }
   ],
   "source": [
    "sin = np.sin(a*np.pi/180)\n",
    "inv = np.arcsin(sin)\n",
    "print (np.degrees(inv))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 195,
   "id": "9ac48ad9-5112-410d-b1d9-d13b293f7681",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[1.00000000e+00 8.66025404e-01 7.07106781e-01 5.00000000e-01\n",
      " 6.12323400e-17]\n",
      "[0.         0.52359878 0.78539816 1.04719755 1.57079633]\n",
      "[ 0. 30. 45. 60. 90.]\n"
     ]
    }
   ],
   "source": [
    "cos = np.cos(a*np.pi/180)\n",
    "print (cos)\n",
    "inv = np.arccos(cos)\n",
    "print (inv)\n",
    "print (np.degrees(inv))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 196,
   "id": "567d01c1-ae1e-4baf-b9f2-13781a09ba32",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[0.00000000e+00 5.77350269e-01 1.00000000e+00 1.73205081e+00\n",
      " 1.63312394e+16]\n",
      "[0.         0.52359878 0.78539816 1.04719755 1.57079633]\n",
      "[ 0. 30. 45. 60. 90.]\n"
     ]
    }
   ],
   "source": [
    "tan = np.tan(a*np.pi/180)\n",
    "print (tan)\n",
    "inv = np.arctan(tan)\n",
    "print (inv)\n",
    "print (np.degrees(inv))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9dd8c607-828c-485f-a6d5-8e91cf861116",
   "metadata": {},
   "source": [
    "## 舍入函数\n",
    "\n",
    "> numpy.around() 函数返回指定数字的四舍五入值。\n",
    "\n",
    "`numpy.around(a,decimals)`\n",
    "\n",
    "> a: 数组\n",
    "\n",
    "> decimals: 舍入的小数位数。 默认值为0。 如果为负，整数将四舍五入到小数点左侧的位置"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 197,
   "id": "1aabeb4a-9cfe-4791-943f-40b9e692c1be",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([  1.,   6., 123.,   1.,  26.])"
      ]
     },
     "execution_count": 197,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a = np.array([1.0,5.55,  123,  0.567,  25.532])  \n",
    "np.around(a)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 198,
   "id": "c6027e6b-045f-4041-9175-466b6d16ef4c",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([  1. ,   5.6, 123. ,   0.6,  25.5])"
      ]
     },
     "execution_count": 198,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.around(a, decimals =  1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 199,
   "id": "136b3de3-b933-4fc5-b68b-0bafcadebc0f",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([  0.,  10., 120.,   0.,  30.])"
      ]
     },
     "execution_count": 199,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.around(a, decimals =  -1)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "917350ce-ef1b-4bb3-aa40-423c2ff9728e",
   "metadata": {},
   "source": [
    "## numpy.floor()\n",
    "\n",
    "> numpy.floor() 返回小于或者等于指定表达式的最大整数，即向下取整。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 200,
   "id": "a03ac005-30a7-4071-b6a7-710243054d68",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([-2.,  1., -1.,  0., 10.])"
      ]
     },
     "execution_count": 200,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a = np.array([-1.7,  1.5,  -0.2,  0.6,  10])\n",
    "np.floor(a)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e90a9e55-b5d2-46a0-b6c0-79477efde1da",
   "metadata": {},
   "source": [
    "## numpy.ceil()\n",
    "\n",
    "> numpy.ceil() 返回大于或者等于指定表达式的最小整数，即向上取整。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 201,
   "id": "96f8cda9-d796-45e0-b9be-dac5153380d3",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([-1.,  2., -0.,  1., 10.])"
      ]
     },
     "execution_count": 201,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.ceil(a)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "77c0dc55-1154-494f-8bb2-ba9f0d8b758a",
   "metadata": {},
   "source": [
    "# 算术函数\n",
    "\n",
    "> NumPy 算术函数包含简单的加减乘除: add()，subtract()，multiply() 和 divide()。\n",
    "\n",
    "> 需要注意的是数组必须具有相同的形状或符合数组广播规则。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 202,
   "id": "63a688e4-d310-487d-ade9-0b4853928b5a",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(array([[0., 1., 2.],\n",
       "        [3., 4., 5.],\n",
       "        [6., 7., 8.]]),\n",
       " array([10, 10, 10]))"
      ]
     },
     "execution_count": 202,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a = np.arange(9, dtype = np.float_).reshape(3,3)\n",
    "b = np.array([10,10,10])\n",
    "a, b"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 203,
   "id": "6ef5cddb-f6c9-451e-909f-66fc38793f8f",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[10., 11., 12.],\n",
       "       [13., 14., 15.],\n",
       "       [16., 17., 18.]])"
      ]
     },
     "execution_count": 203,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.add(a,b)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 204,
   "id": "acdf0ed8-c715-48ce-a972-e2978a00d86f",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[-10.,  -9.,  -8.],\n",
       "       [ -7.,  -6.,  -5.],\n",
       "       [ -4.,  -3.,  -2.]])"
      ]
     },
     "execution_count": 204,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.subtract(a,b)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 205,
   "id": "2f5fd88b-6ff6-4465-9b2c-f2118ae8e9d3",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 0., 10., 20.],\n",
       "       [30., 40., 50.],\n",
       "       [60., 70., 80.]])"
      ]
     },
     "execution_count": 205,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.multiply(a,b)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 206,
   "id": "acaf27ec-fe01-419d-97c8-053df2a0c66e",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[0. , 0.1, 0.2],\n",
       "       [0.3, 0.4, 0.5],\n",
       "       [0.6, 0.7, 0.8]])"
      ]
     },
     "execution_count": 206,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.divide(a,b)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "49be7ff9-0621-447e-aec2-e1a155234763",
   "metadata": {},
   "source": [
    "## numpy.reciprocal()\n",
    "\n",
    "> numpy.reciprocal() 函数返回参数逐元素的倒数。如 1/4 倒数为 4/1。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 207,
   "id": "f79c1458-fd2e-4c1d-9912-9c4dc2e06ff4",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([4.       , 0.7518797, 1.       , 0.01     ])"
      ]
     },
     "execution_count": 207,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a = np.array([0.25,  1.33,  1,  100])\n",
    "np.reciprocal(a)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c117bbe2-81cd-4656-81f6-9606f53bb997",
   "metadata": {},
   "source": [
    "## numpy.power()\n",
    "\n",
    "> numpy.power() 函数将第一个输入数组中的元素作为底数，计算它与第二个输入数组中相应元素的幂。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 208,
   "id": "9f0ad643-1708-4379-93c5-23ce3539ed57",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([    100,   10000, 1000000])"
      ]
     },
     "execution_count": 208,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a = np.array([10,100,1000])\n",
    "np.power(a,2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 209,
   "id": "01620d65-dba8-444b-acc6-9597233fa3f7",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([        10,      10000, 1000000000])"
      ]
     },
     "execution_count": 209,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "b = np.array([1,2,3])\n",
    "np.power(a,b)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f9f63598-a52b-4f6a-a17b-5a20cb46c9f4",
   "metadata": {},
   "source": [
    "## numpy.mod()\n",
    "\n",
    "> numpy.mod() 计算输入数组中相应元素的相除后的余数。 函数 numpy.remainder() 也产生相同的结果。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 210,
   "id": "f7cd696b-dd30-4ea2-a707-1ca41228de68",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([1, 0, 2])"
      ]
     },
     "execution_count": 210,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a = np.array([10,20,30])\n",
    "b = np.array([3,5,7])\n",
    "np.mod(a,b)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 211,
   "id": "a0f4c470-e684-41c2-bd40-e32016ea449e",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([1, 0, 2])"
      ]
     },
     "execution_count": 211,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.remainder(a,b)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "bdd33a9b-1d29-425c-9762-b08a324165a1",
   "metadata": {},
   "source": [
    "# 统计函数\n",
    "\n",
    "> NumPy 提供了很多统计函数，用于从数组中查找最小元素，最大元素，百分位标准差和方差等。"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "106fc038-3023-42c6-a354-b4ea80c9be0e",
   "metadata": {},
   "source": [
    "## numpy.amin()\n",
    "\n",
    "> numpy.amin() 用于计算数组中的元素沿指定轴的最小值。\n",
    "\n",
    "`numpy.amin(a, axis=None, out=None, keepdims=<no value>, initial=<no value>, where=<no value>)`\n",
    "\n",
    "*    a: 输入的数组，可以是一个NumPy数组或类似数组的对象。\n",
    "    \n",
    "*    axis: 可选参数，用于指定在哪个轴上计算最小值。\n",
    "    如果不提供此参数，则返回整个数组的最小值。可以是一个整数表示轴的索引，也可以是一个元组表示多个轴。\n",
    "    \n",
    "*    out: 可选参数，用于指定结果的存储位置。\n",
    "    \n",
    "*    keepdims: 可选参数，如果为True，将保持结果数组的维度数目与输入数组相同。如果为False（默认值），则会去除计算后维度为1的轴。\n",
    "    \n",
    "*    initial: 可选参数，用于指定一个初始值，然后在数组的元素上计算最小值。\n",
    "    \n",
    "*    where: 可选参数，一个布尔数组，用于指定仅考虑满足条件的元素。"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e9c6ff50-f97c-440b-b7ab-7465e6bdf2b2",
   "metadata": {},
   "source": [
    "## numpy.amax()\n",
    "\n",
    "> 用于计算数组中的元素沿指定轴的最大值。\n",
    "\n",
    "`numpy.amax(a, axis=None, out=None, keepdims=<no value>, initial=<no value>, where=<no value>)`\n",
    "\n",
    "*    a: 输入的数组，可以是一个NumPy数组或类似数组的对象。\n",
    "\n",
    "*    axis: 可选参数，用于指定在哪个轴上计算最大值。如果不提供此参数，则返回整个数组的最大值。可以是一个整数表示轴的索引，也可以是一个元组表示多个轴。\n",
    "\n",
    "*    out: 可选参数，用于指定结果的存储位置。\n",
    "\n",
    "*    keepdims: 可选参数，如果为True，将保持结果数组的维度数目与输入数组相同。如果为False（默认值），则会去除计算后维度为1的轴。\n",
    "\n",
    "*    initial: 可选参数，用于指定一个初始值，然后在数组的元素上计算最大值。\n",
    "\n",
    "*    where: 可选参数，一个布尔数组，用于指定仅考虑满足条件的元素。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 212,
   "id": "bf5cc3e1-8a8b-461e-b39d-75bf79f7cf5d",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([3, 3, 2])"
      ]
     },
     "execution_count": 212,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a = np.array([[3,7,5],[8,4,3],[2,4,9]])  \n",
    "np.amin(a,1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 213,
   "id": "3c940046-eef3-415d-8503-3737fa75b325",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([2, 4, 3])"
      ]
     },
     "execution_count": 213,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.amin(a,0)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 214,
   "id": "bf3373b0-e669-4833-9e81-fdadf4a945ac",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "9"
      ]
     },
     "execution_count": 214,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.amax(a)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 215,
   "id": "1271fbfc-2dfe-4f49-8d18-34320a2c8d30",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([8, 7, 9])"
      ]
     },
     "execution_count": 215,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.amax(a, axis=0)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "77705b4a-5fed-4430-b73d-dfedd3ba1a39",
   "metadata": {},
   "source": [
    "## numpy.ptp()\n",
    "\n",
    "> numpy.ptp() 函数计算数组中元素最大值与最小值的差（最大值 - 最小值）。\n",
    "\n",
    "`numpy.ptp(a, axis=None, out=None, keepdims=<no value>, initial=<no value>, where=<no value>)`\n",
    "\n",
    "*    a: 输入的数组，可以是一个 NumPy 数组或类似数组的对象。\n",
    "    \n",
    "*    axis: 可选参数，用于指定在哪个轴上计算峰-峰值。如果不提供此参数，则返回整个数组的峰-峰值。可以是一个整数表示轴的索引，也可以是一个元组表示多个轴。\n",
    "    \n",
    "*    out: 可选参数，用于指定结果的存储位置。\n",
    "    \n",
    "*    keepdims: 可选参数，如果为 True，将保持结果数组的维度数目与输入数组相同。如果为 False（默认值），则会去除计算后维度为1的轴。\n",
    "    \n",
    "*    initial: 可选参数，用于指定一个初始值，然后在数组的元素上计算峰-峰值。\n",
    "    \n",
    "*    where: 可选参数，一个布尔数组，用于指定仅考虑满足条件的元素。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 216,
   "id": "085fe85b-4a81-4a85-b1b8-bc991ec72926",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "7"
      ]
     },
     "execution_count": 216,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a = np.array([[3,7,5],[8,4,3],[2,4,9]])  \n",
    "np.ptp(a)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 217,
   "id": "68911452-133e-4afb-b2cc-b5377390832d",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([4, 5, 7])"
      ]
     },
     "execution_count": 217,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.ptp(a, axis =  1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 218,
   "id": "dbd4ab38-c8e5-44ee-b1fe-e1d9ebce3710",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([6, 3, 6])"
      ]
     },
     "execution_count": 218,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.ptp(a, axis =  0)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8fb8e294-2ce4-4fea-a176-392a86efa937",
   "metadata": {},
   "source": [
    "## numpy.percentile()\n",
    "\n",
    "> 百分位数是统计中使用的度量，表示小于这个值的观察值的百分比。 函数numpy.percentile()接受以下参数。\n",
    "\n",
    "`numpy.percentile(a, q, axis)`\n",
    "\n",
    "*    a: 输入数组\n",
    "\n",
    "*    q: 要计算的百分位数，在 0 ~ 100 之间\n",
    "\n",
    "*    axis: 沿着它计算百分位数的轴\n",
    "\n",
    "> 首先明确百分位数：\n",
    "\n",
    "> 第 p 个百分位数是这样一个值，它使得至少有 p% 的数据项小于或等于这个值，且至少有 (100-p)% 的数据项大于或等于这个值。\n",
    "\n",
    "> 举个例子：高等院校的入学考试成绩经常以百分位数的形式报告。\n",
    "\n",
    "> 比如，假设某个考生在入学考试中的语文部分的原始分数为 54 分。\n",
    "\n",
    "> 相对于参加同一考试的其他学生来说，他的成绩如何并不容易知道。\n",
    "\n",
    "> 但是如果原始分数54分恰好对应的是第70百分位数，我们就能知道大约70%的学生的考分比他低，而约30%的学生考分比他高。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 219,
   "id": "1c18f3a9-238c-4b41-866c-25e44afa446e",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "3.5"
      ]
     },
     "execution_count": 219,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a = np.array([[10, 7, 4], [3, 2, 1]])\n",
    "np.percentile(a, 50)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 220,
   "id": "8824f1fe-bc42-486b-b6b9-580e6203fd71",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([6.5, 4.5, 2.5])"
      ]
     },
     "execution_count": 220,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.percentile(a, 50, axis=0)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 221,
   "id": "40bc76fa-384b-443e-9b54-8cfeb3c85f49",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([7., 2.])"
      ]
     },
     "execution_count": 221,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.percentile(a, 50, axis=1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 222,
   "id": "323e4d78-275e-4a98-93b6-03ddf9c18fe5",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[7.],\n",
       "       [2.]])"
      ]
     },
     "execution_count": 222,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.percentile(a, 50, axis=1, keepdims=True)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6e67d67c-fae5-498c-a881-0ce6c2953631",
   "metadata": {},
   "source": [
    "## numpy.median()\n",
    "\n",
    "> numpy.median() 函数用于计算数组 a 中元素的中位数（中值）\n",
    "\n",
    "`numpy.median(a, axis=None, out=None, overwrite_input=False, keepdims=<no value>)`\n",
    "\n",
    "*    a: 输入的数组，可以是一个 NumPy 数组或类似数组的对象。\n",
    "    \n",
    "*    axis: 可选参数，用于指定在哪个轴上计算中位数。如果不提供此参数，则计算整个数组的中位数。可以是一个整数表示轴的索引，也可以是一个元组表示多个轴。\n",
    "    \n",
    "*    out: 可选参数，用于指定结果的存储位置。\n",
    "    \n",
    "*    overwrite_input: 可选参数，如果为True，则允许在计算中使用输入数组的内存。这可能会在某些情况下提高性能，但可能会修改输入数组的内容。\n",
    "    \n",
    "*    keepdims: 可选参数，如果为True，将保持结果数组的维度数目与输入数组相同。如果为False（默认值），则会去除计算后维度为1的轴。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 223,
   "id": "a3a1d582-482f-4028-ad49-48f33a70ead4",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "65.0"
      ]
     },
     "execution_count": 223,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a = np.array([[30,65,70],[80,95,10],[50,90,60]])  \n",
    "np.median(a)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 224,
   "id": "fc50877c-9a68-4293-a811-1d9ea1423f0c",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([50., 90., 60.])"
      ]
     },
     "execution_count": 224,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.median(a, axis =  0)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 225,
   "id": "db581865-8259-43cd-8d9c-817005a37f5a",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([65., 80., 60.])"
      ]
     },
     "execution_count": 225,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.median(a, axis =  1)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "bec089cf-5d77-438e-80e6-70bbd5e7b5b4",
   "metadata": {},
   "source": [
    "## numpy.mean()\n",
    "\n",
    "> numpy.mean() 函数返回数组中元素的算术平均值，如果提供了轴，则沿其计算。算术平均值是沿轴的元素的总和除以元素的数量。\n",
    "\n",
    "`numpy.mean(a, axis=None, dtype=None, out=None, keepdims=<no value>)`\n",
    "\n",
    "*    a: 输入的数组，可以是一个 NumPy 数组或类似数组的对象。\n",
    "*    axis: 可选参数，用于指定在哪个轴上计算平均值。如果不提供此参数，则计算整个数组的平均值。可以是一个整数表示轴的索引，也可以是一个元组表示多个轴。\n",
    "*    dtype: 可选参数，用于指定输出的数据类型。如果不提供，则根据输入数据的类型选择合适的数据类型。\n",
    "*    out: 可选参数，用于指定结果的存储位置。\n",
    "*    keepdims: 可选参数，如果为True，将保持结果数组的维度数目与输入数组相同。如果为False（默认值），则会去除计算后维度为1的轴。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 226,
   "id": "1b6abe0e-0f76-413a-aca8-b2e02c57f9f6",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "3.6666666666666665"
      ]
     },
     "execution_count": 226,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a = np.array([[1,2,3],[3,4,5],[4,5,6]])  \n",
    "np.mean(a)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 227,
   "id": "6ef3034f-88f9-49a3-be06-b60223972707",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([2.66666667, 3.66666667, 4.66666667])"
      ]
     },
     "execution_count": 227,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.mean(a, axis =  0)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 228,
   "id": "b8fd5e8a-1fe8-4094-871a-b27d51cebd0e",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([2., 4., 5.])"
      ]
     },
     "execution_count": 228,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.mean(a, axis =  1)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f6e9c250-c5d4-4d57-901e-36bf2346c3de",
   "metadata": {},
   "source": [
    "## numpy.average()\n",
    "\n",
    "> numpy.average() 函数根据在另一个数组中给出的各自的权重计算数组中元素的加权平均值。\n",
    "\n",
    "> 该函数可以接受一个轴参数。 如果没有指定轴，则数组会被展开。\n",
    "\n",
    "> 加权平均值即将各数值乘以相应的权数，然后加总求和得到总体值，再除以总的单位数。\n",
    "\n",
    "> 考虑数组[1,2,3,4]和相应的权重[4,3,2,1]，通过将相应元素的乘积相加，并将和除以权重的和，来计算加权平均值。\n",
    "\n",
    "> 加权平均值 = (1*4+2*3+3*2+4*1)/(4+3+2+1)\n",
    "\n",
    "`numpy.average(a, axis=None, weights=None, returned=False)`\n",
    "\n",
    "*    a: 输入的数组，可以是一个 NumPy 数组或类似数组的对象。\n",
    "*    axis: 可选参数，用于指定在哪个轴上计算加权平均值。如果不提供此参数，则计算整个数组的加权平均值。可以是一个整数表示轴的索引，也可以是一个元组表示多个轴。\n",
    "*    weights: 可选参数，用于指定对应数据点的权重。如果不提供权重数组，则默认为等权重。\n",
    "*    returned: 可选参数，如果为True，将同时返回加权平均值和权重总和。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 229,
   "id": "ed9864b7-3bb6-4be5-b470-6112641f23a5",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "2.5"
      ]
     },
     "execution_count": 229,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a = np.array([1,2,3,4])  \n",
    "np.average(a)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 230,
   "id": "db4df58d-03fc-4e44-a6cf-8828ffa55dac",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "2.0"
      ]
     },
     "execution_count": 230,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "wts = np.array([4,3,2,1]) \n",
    "np.average(a,weights = wts)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 231,
   "id": "a56e44ff-2a05-4e46-87e2-ed432059bf20",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(2.0, 10.0)"
      ]
     },
     "execution_count": 231,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.average([1,2,3,  4],weights =  [4,3,2,1], returned =  True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 232,
   "id": "94245dac-4d48-4f9d-8cd0-c11efcc5f2fe",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([0.625, 2.625, 4.625])"
      ]
     },
     "execution_count": 232,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a = np.arange(6).reshape(3,2)\n",
    "wt = np.array([3,5])\n",
    "np.average(a, axis =  1, weights = wt)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 233,
   "id": "bc4f7f7e-d5f6-4a14-adff-9acf38aa6533",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(array([0.625, 2.625, 4.625]), array([8., 8., 8.]))"
      ]
     },
     "execution_count": 233,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.average(a, axis =  1, weights = wt, returned =  True)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b97637d0-cdcb-4f4c-93f9-3d8226a73769",
   "metadata": {},
   "source": [
    "## 标准差\n",
    "\n",
    "> 标准差是一组数据平均值分散程度的一种度量。\n",
    "\n",
    "> 标准差是方差的算术平方根。\n",
    "\n",
    "> 标准差公式如下：\n",
    "\n",
    "`std = sqrt(mean((x - x.mean())**2))`\n",
    "\n",
    "> 如果数组是 [1，2，3，4]，则其平均值为 2.5。 因此，差的平方是 [2.25,0.25,0.25,2.25]，并且再求其平均值的平方根除以 4，即 sqrt(5/4) ，结果为 1.1180339887498949。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 234,
   "id": "e88c9455-0498-49ca-824c-c9066a9dad82",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "1.118033988749895"
      ]
     },
     "execution_count": 234,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.std([1,2,3,4])"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ce5c0586-b2ed-4ff3-8246-0fc10a7d9648",
   "metadata": {},
   "source": [
    "## 方差\n",
    "\n",
    "> 统计中的方差（样本方差）是每个样本值与全体样本值的平均数之差的平方值的平均数。\n",
    "\n",
    "`mean((x - x.mean())** 2)`\n",
    "\n",
    "> 换句话说，标准差是方差的平方根。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 235,
   "id": "01253dd3-87d2-43b8-ad38-154973336393",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "1.25"
      ]
     },
     "execution_count": 235,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.var([1,2,3,4])"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9701454f-3ed9-441b-98c1-4f45ad90f9de",
   "metadata": {},
   "source": [
    "# 排序、条件筛选函数\n",
    "\n",
    "种类|速度|最坏情况|工作空间|稳定性\n",
    "--:|:--:|:--:|:--:|:--:\n",
    "'quicksort'（快速排序）|1|O(n^2)|0|否\n",
    "'mergesort'（归并排序）|2|O(n*log(n))|~n/2|是\n",
    "'heapsort'（堆排序）|3|O(n*log(n))|0|否"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1ec7be20-c1b0-4b77-8016-c7d48e241c65",
   "metadata": {},
   "source": [
    "## numpy.sort()\n",
    "\n",
    "> numpy.sort() 函数返回输入数组的排序副本。函数格式如下：\n",
    "\n",
    "`numpy.sort(a, axis, kind, order)`\n",
    "\n",
    "*    a: 要排序的数组\n",
    "*    axis: 沿着它排序数组的轴，如果没有数组会被展开，沿着最后的轴排序， axis=0 按列排序，axis=1 按行排序\n",
    "*    kind: 默认为'quicksort'（快速排序）\n",
    "*    order: 如果数组包含字段，则是要排序的字段"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 236,
   "id": "0011e9a1-63af-451b-a4e2-c162a13f0610",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[3, 7],\n",
       "       [1, 9]])"
      ]
     },
     "execution_count": 236,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a = np.array([[3,7],[9,1]])  \n",
    "np.sort(a)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 237,
   "id": "8c3b28cf-e260-4b68-994e-5f5d96e6ed37",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[3, 1],\n",
       "       [9, 7]])"
      ]
     },
     "execution_count": 237,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.sort(a, axis =  0)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 238,
   "id": "86b38d98-798f-4577-8638-f2baacd5c412",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([(b'raju', 21), (b'anil', 25), (b'ravi', 17), (b'amar', 27)],\n",
       "      dtype=[('name', 'S10'), ('age', '<i8')])"
      ]
     },
     "execution_count": 238,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "dt = np.dtype([('name',  'S10'),('age',  int)]) \n",
    "a = np.array([(\"raju\",21),(\"anil\",25),(\"ravi\",  17),  (\"amar\",27)], dtype = dt)  \n",
    "a"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 239,
   "id": "1c34329a-0f54-46c9-87e4-6ab27fd2815f",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([(b'amar', 27), (b'anil', 25), (b'raju', 21), (b'ravi', 17)],\n",
       "      dtype=[('name', 'S10'), ('age', '<i8')])"
      ]
     },
     "execution_count": 239,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.sort(a, order =  'name')"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "bfcdfaf7-0dc2-4560-a36b-324113acf054",
   "metadata": {},
   "source": [
    "## numpy.argsort()\n",
    "\n",
    "> numpy.argsort() 函数返回的是数组值从小到大的索引值。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 240,
   "id": "e626969c-7c0f-4e8f-84ba-5be10d084cd1",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([1, 2, 0])"
      ]
     },
     "execution_count": 240,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "x = np.array([3,  1,  2])\n",
    "y = np.argsort(x)\n",
    "y"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 241,
   "id": "01270846-28d3-474d-b89f-58154eccb2f5",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([1, 2, 3])"
      ]
     },
     "execution_count": 241,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "x[y]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 242,
   "id": "17b7378d-c397-4c0b-8c94-1c55f2180adf",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1 2 3 "
     ]
    }
   ],
   "source": [
    "for i in y:\n",
    "    print (x[i], end=\" \")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f897e021-b195-4af0-8c9c-2deee9d8d66e",
   "metadata": {},
   "source": [
    "## numpy.lexsort()\n",
    "\n",
    "> numpy.lexsort() 用于对多个序列进行排序。把它想象成对电子表格进行排序，每一列代表一个序列，排序时优先照顾靠后的列。\n",
    "这里举一个应用场景：小升初考试，重点班录取学生按照总成绩录取。在总成绩相同时，数学成绩高的优先录取，在总成绩和数学成绩都相同时，按照英语成绩录取…… 这里，总成绩排在电子表格的最后一列，数学成绩在倒数第二列，英语成绩在倒数第三列。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 243,
   "id": "201364df-329b-472b-be12-94762fc68380",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([3, 1, 0, 2])"
      ]
     },
     "execution_count": 243,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "nm =  ('raju','anil','ravi','amar')\n",
    "dv =  ('f.y.',  's.y.',  's.y.',  'f.y.')\n",
    "ind = np.lexsort((dv,nm))\n",
    "ind"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 244,
   "id": "de58de46-eff7-4954-830a-ed9edf4ae065",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['amar, f.y.', 'anil, s.y.', 'raju, f.y.', 'ravi, s.y.']"
      ]
     },
     "execution_count": 244,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "[nm[i]  +  \", \"  + dv[i]  for i in ind]"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "517467b5-77f8-4d71-ad21-b32121859df5",
   "metadata": {},
   "source": [
    "## msort、sort_complex、partition、argpartition\n",
    "\n",
    "函数|描述\n",
    "--:|:--\n",
    "msort(a)|数组按第一个轴排序，返回排序后的数组副本。np.msort(a) 相等于 np.sort(a, axis=0)。\n",
    "sort_complex(a)|对复数按照先实部后虚部的顺序进行排序。\n",
    "partition(a, kth[, axis, kind, order])|指定一个数，对数组进行分区\n",
    "argpartition(a, kth[, axis, kind, order])|可以通过关键字 kind 指定算法沿着指定轴对数组进行分区"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 245,
   "id": "16d80a73-ed01-4d17-9295-8ffbd1f3b0a4",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([1.+0.j, 2.+0.j, 3.+0.j, 5.+0.j, 6.+0.j])"
      ]
     },
     "execution_count": 245,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 复数排序：\n",
    "np.sort_complex([5, 3, 6, 2, 1])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 246,
   "id": "825ccd83-cbe7-4a58-b3dd-d1c931c28126",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([1.+2.j, 2.-1.j, 3.-3.j, 3.-2.j, 3.+5.j])"
      ]
     },
     "execution_count": 246,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.sort_complex([1 + 2j, 2 - 1j, 3 - 2j, 3 - 3j, 3 + 5j])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 247,
   "id": "fbf9ec5d-13f0-4442-8dc8-08538134fda0",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([2, 1, 3, 4])"
      ]
     },
     "execution_count": 247,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# partition() 分区排序：\n",
    "a = np.array([3, 4, 2, 1])\n",
    "np.partition(a, 3)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 248,
   "id": "062079cb-bc4b-4050-a087-06c4d9bf07e6",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([1, 2, 3, 4])"
      ]
     },
     "execution_count": 248,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.partition(a, (1, 3))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 249,
   "id": "060c1410-a255-403a-9c0e-ed58aa038d7e",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "10"
      ]
     },
     "execution_count": 249,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 找到数组的第 3 小（index=2）的值和第 2 大（index=-2）的值\n",
    "arr = np.array([46, 57, 23, 39, 1, 10, 0, 120])\n",
    "arr[np.argpartition(arr, 2)[2]]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 250,
   "id": "5be51d01-bd14-4240-a087-6b4f821a32f4",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "57"
      ]
     },
     "execution_count": 250,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr[np.argpartition(arr, -2)[-2]]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 251,
   "id": "d3ca3776-ea31-43db-b237-6959e29399dc",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "10"
      ]
     },
     "execution_count": 251,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 同时找到第 3 和第 4 小的值。\n",
    "#注意这里，用 [2,3] 同时将第 3 和第 4 小的排序好，然后可以分别通过下标 [2] 和 [3] 取得。\n",
    "arr[np.argpartition(arr, [2,3])[2]]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 252,
   "id": "9f493392-37f9-4f40-8ff8-1f2bbf556c11",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "23"
      ]
     },
     "execution_count": 252,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr[np.argpartition(arr, [2,3])[3]]"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e49a95a1-4b9c-49a3-a5b1-723246dca609",
   "metadata": {},
   "source": [
    "## numpy.argmax() 和 numpy.argmin()\n",
    "\n",
    "> numpy.argmax() 和 numpy.argmin()函数分别沿给定轴返回最大和最小元素的索引。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 253,
   "id": "ea71cbd3-28da-431a-8d29-5b478184635e",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "7"
      ]
     },
     "execution_count": 253,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a = np.array([[30,40,70],[80,20,10],[50,90,60]])\n",
    "np.argmax(a)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 254,
   "id": "fef37c14-b54f-4cd8-885e-c8d304d5dd07",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([1, 2, 0])"
      ]
     },
     "execution_count": 254,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.argmax(a, axis =  0)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 255,
   "id": "146a79a8-9165-491e-baec-1f351c509112",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([2, 0, 1])"
      ]
     },
     "execution_count": 255,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.argmax(a, axis =  1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 256,
   "id": "baa5fab6-c692-4050-8b93-a2cbda7ef8ce",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "5"
      ]
     },
     "execution_count": 256,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.argmin(a)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 257,
   "id": "d7b58171-0823-47ee-aef4-a6b88ba41908",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "10"
      ]
     },
     "execution_count": 257,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a.flatten()[np.argmin(a)]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 258,
   "id": "fac4ff70-6123-47db-b0f4-4427ec507203",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([0, 1, 1])"
      ]
     },
     "execution_count": 258,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.argmin(a, axis =  0)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 259,
   "id": "d9ae1ca3-d428-4b02-abd7-dd63c4a1d6ad",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([0, 2, 0])"
      ]
     },
     "execution_count": 259,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.argmin(a, axis =  1)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9634e016-4c7e-4f3f-b310-44027257f8b7",
   "metadata": {},
   "source": [
    "## numpy.nonzero()\n",
    "\n",
    "> numpy.nonzero() 函数返回输入数组中非零元素的索引。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 260,
   "id": "09b999ea-0df4-4cb7-9ebf-305e5afdb010",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(array([0, 0, 1, 1, 2, 2]), array([0, 1, 1, 2, 0, 2]))"
      ]
     },
     "execution_count": 260,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a = np.array([[30,40,0],[0,20,10],[50,0,60]])\n",
    "np.nonzero (a)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3c347bdd-544b-4455-b7b6-da019099df4f",
   "metadata": {},
   "source": [
    "## numpy.where()\n",
    "\n",
    "> numpy.where() 函数返回输入数组中满足给定条件的元素的索引。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 261,
   "id": "c062431a-36f4-42bc-96d7-ee0d07fce69a",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(array([[0., 1., 2.],\n",
       "        [3., 4., 5.],\n",
       "        [6., 7., 8.]]),\n",
       " (array([1, 1, 2, 2, 2]), array([1, 2, 0, 1, 2])))"
      ]
     },
     "execution_count": 261,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "x = np.arange(9.).reshape(3,  3)  \n",
    "y = np.where(x >  3)  \n",
    "x, y"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 262,
   "id": "7a0beab6-4eb8-4aab-afde-3187ca4c9d82",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([4., 5., 6., 7., 8.])"
      ]
     },
     "execution_count": 262,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "x[y]"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "eb894cb3-3ef4-4a00-8968-cfeffe75eee2",
   "metadata": {
    "tags": []
   },
   "source": [
    "## numpy.extract()\n",
    "\n",
    "> numpy.extract() 函数根据某个条件从数组中抽取元素，返回满条件的元素。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 263,
   "id": "45f48590-aee8-4c5c-98b2-04727a9798cf",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[0., 1., 2.],\n",
       "       [3., 4., 5.],\n",
       "       [6., 7., 8.]])"
      ]
     },
     "execution_count": 263,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "x = np.arange(9.).reshape(3,  3)\n",
    "x"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 264,
   "id": "b927ff40-df8e-4cf2-974b-15cd860a788e",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ True, False,  True],\n",
       "       [False,  True, False],\n",
       "       [ True, False,  True]])"
      ]
     },
     "execution_count": 264,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "y = np.mod(x,2)  ==  0\n",
    "y"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 265,
   "id": "3a660c46-e0af-485c-97c7-ffb05aad05d1",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([0., 2., 4., 6., 8.])"
      ]
     },
     "execution_count": 265,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.extract(y, x)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7c9a019f-0832-40f1-a1d1-7fe6d0256686",
   "metadata": {},
   "source": [
    "# 字节交换\n",
    "\n",
    "> 在几乎所有的机器上，多字节对象都被存储为连续的字节序列。字节顺序，是跨越多字节的程序对象的存储规则。\n",
    "\n",
    "> 大端模式：指数据的高字节保存在内存的低地址中，而数据的低字节保存在内存的高地址中，这样的存储模式有点儿类似于把数据当作字符串顺序处理：地址由小向大增加，而数据从高位往低位放；这和我们的阅读习惯一致。\n",
    "\n",
    "> 小端模式：指数据的高字节保存在内存的高地址中，而数据的低字节保存在内存的低地址中，这种存储模式将地址的高低和数据位权有效地结合起来，高地址部分权值高，低地址部分权值低。\n",
    "\n",
    "> 例如在 C 语言中，一个类型为 int 的变量 x 地址为 0x100，那么其对应地址表达式&x的值为 0x100。且x的四个字节将被存储在存储器的 0x100, 0x101, 0x102, 0x103位置。"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7f059ffa-a5bc-415c-a0ed-486318190178",
   "metadata": {},
   "source": [
    "## numpy.ndarray.byteswap()\n",
    "\n",
    "> numpy.ndarray.byteswap() 函数将 ndarray 中每个元素中的字节进行大小端转换。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 266,
   "id": "7f88148e-f941-4e23-b920-765cda16dcc3",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([   1,  256, 8755], dtype=int16)"
      ]
     },
     "execution_count": 266,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a = np.array([1,  256,  8755], dtype = np.int16)\n",
    "a"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 267,
   "id": "de68fcdb-7536-46e4-beab-c40a515bb2f6",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<map at 0x7f352f1aac18>"
      ]
     },
     "execution_count": 267,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "map(hex,a)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 268,
   "id": "2710f07a-3b43-4201-b1f5-50ea91fa26f9",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([  256,     1, 13090], dtype=int16)"
      ]
     },
     "execution_count": 268,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a.byteswap(True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 269,
   "id": "10b545b6-8d33-40db-b37a-4f771bd473e3",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<map at 0x7f352f1c9c18>"
      ]
     },
     "execution_count": 269,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "map(hex,a)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a06a85e1-c9c2-4df0-b1b5-aee116df5128",
   "metadata": {},
   "source": [
    "# 副本和视图\n",
    "\n",
    ">副本是一个数据的完整的拷贝，如果我们对副本进行修改，它不会影响到原始数据，物理内存不在同一位置。\n",
    "\n",
    ">视图是数据的一个别称或引用，通过该别称或引用亦便可访问、操作原有数据，但原有数据不会产生拷贝。如果我们对视图进行修改，它会影响到原始数据，物理内存在同一位置。\n",
    "\n",
    "**视图一般发生在：**\n",
    "\n",
    "1.numpy 的切片操作返回原数据的视图。\n",
    "2.调用 ndarray 的 view() 函数产生一个视图。\n",
    "\n",
    "**副本一般发生在：**\n",
    "\n",
    "*    Python 序列的切片操作，调用deepCopy()函数。\n",
    "*    调用 ndarray 的 copy() 函数产生一个副本。\n",
    "\n",
    "__无复制__\n",
    "\n",
    ">简单的赋值不会创建数组对象的副本。 相反，它使用原始数组的相同id()来访问它。 id()返回 Python 对象的通用标识符，类似于 C 中的指针。\n",
    "\n",
    ">此外，一个数组的任何变化都反映在另一个数组上。 例如，一个数组的形状改变也会改变另一个数组的形状。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 270,
   "id": "0cb1fad5-3762-437f-8411-c28d516a35bb",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(array([0, 1, 2, 3, 4, 5]), 139866401776984)"
      ]
     },
     "execution_count": 270,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a = np.arange(6)\n",
    "a, id(a)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 271,
   "id": "0e45f6ff-208f-495b-8c51-abbad7689522",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(array([0, 1, 2, 3, 4, 5]), 139866401776984)"
      ]
     },
     "execution_count": 271,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "b = a\n",
    "b, id(b)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 272,
   "id": "2f2c5d74-68f3-40fe-9ab6-98cf32a811bf",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(array([[0, 1],\n",
       "        [2, 3],\n",
       "        [4, 5]]),\n",
       " array([[0, 1],\n",
       "        [2, 3],\n",
       "        [4, 5]]))"
      ]
     },
     "execution_count": 272,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "b.shape =  3,2\n",
    "b, a"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "755fd916-039c-41cf-a6b7-d0fc83a6b0ee",
   "metadata": {
    "tags": []
   },
   "source": [
    "## 视图或浅拷贝\n",
    "\n",
    ">ndarray.view() 方会创建一个新的数组对象，该方法创建的新数组的维数变化不会改变原始数据的维数。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 273,
   "id": "14a99d06-ea93-44ab-82b9-2e65a69b38cd",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[0, 1],\n",
       "       [2, 3],\n",
       "       [4, 5]])"
      ]
     },
     "execution_count": 273,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a = np.arange(6).reshape(3,2)  \n",
    "a"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 274,
   "id": "7309bf88-a3cc-49f4-97d8-98508b6f145a",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(array([[0, 1],\n",
       "        [2, 3],\n",
       "        [4, 5]]),\n",
       " 139866401206408,\n",
       " 139866400764392)"
      ]
     },
     "execution_count": 274,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "b = a.view()  \n",
    "b, id(a), id(b)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 275,
   "id": "745afaa2-1716-437e-a72e-7973822350fa",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(array([[0, 1, 2],\n",
       "        [3, 4, 5]]),\n",
       " array([[0, 1],\n",
       "        [2, 3],\n",
       "        [4, 5]]))"
      ]
     },
     "execution_count": 275,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "b.shape =  2,3\n",
    "b, a"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e221c866-5a64-4c35-a331-2113583b3f7f",
   "metadata": {
    "tags": []
   },
   "source": [
    ">使用切片创建视图修改数据会影响到原始数组"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 276,
   "id": "a7b4ab4c-6cb8-44c3-9be7-9cf3cb3aff1e",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11])"
      ]
     },
     "execution_count": 276,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a = np.arange(12)\n",
    "a"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 277,
   "id": "e7513d21-b1af-4e48-a163-079fcf330abf",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([  0,   1,   2,   3, 123, 234,   6,   7,   8,   9,  10,  11])"
      ]
     },
     "execution_count": 277,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "b=a[3:]\n",
    "c=a[3:]\n",
    "b[1]=123\n",
    "c[2]=234\n",
    "a"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 278,
   "id": "624feea9-81ce-4157-b336-99ecfba65895",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(139866401034904, 139866401037192, 139866401490792)"
      ]
     },
     "execution_count": 278,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "id(b),id(c),id(a[3:])"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "425e88ca-1c0e-4c32-ad70-4c6fef861589",
   "metadata": {},
   "source": [
    "# 副本或深拷贝\n",
    "\n",
    ">ndarray.copy() 函数创建一个副本。 对副本数据进行修改，不会影响到原始数据，它们物理内存不在同一位置。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 279,
   "id": "3e89cb7e-7d70-4fe5-9c8c-8ccb2328f4e9",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[10, 10],\n",
       "       [ 2,  3],\n",
       "       [ 4,  5]])"
      ]
     },
     "execution_count": 279,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a = np.array([[10,10],  [2,3],  [4,5]])\n",
    "a"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 280,
   "id": "99cd02ce-925f-46f2-8fd6-307ec79b37af",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(array([[10, 10],\n",
       "        [ 2,  3],\n",
       "        [ 4,  5]]),\n",
       " False)"
      ]
     },
     "execution_count": 280,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "b = a.copy()\n",
    "b, b is a"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 281,
   "id": "42a295c2-face-4774-958c-b0729e2ef0d1",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(array([[100,  10],\n",
       "        [  2,   3],\n",
       "        [  4,   5]]),\n",
       " array([[10, 10],\n",
       "        [ 2,  3],\n",
       "        [ 4,  5]]))"
      ]
     },
     "execution_count": 281,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "b[0,0]  =  100\n",
    "b, a"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "dcc5fe24-1b1b-4850-8117-65f7dbd9f280",
   "metadata": {},
   "source": [
    "# 矩阵库(Matrix)\n",
    "\n",
    ">NumPy 中包含了一个矩阵库 numpy.matlib，该模块中的函数返回的是一个矩阵，而不是 ndarray 对象。\n",
    "\n",
    ">一个 的矩阵是一个由行（row）列（column）元素排列成的矩形阵列。\n",
    "\n",
    ">矩阵里的元素可以是数字、符号或数学式。"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "57bc3ef9-2f39-4933-ae48-4f2fecb0ac44",
   "metadata": {},
   "source": [
    "## 转置矩阵\n",
    "\n",
    ">NumPy 中除了可以使用 numpy.transpose 函数来对换数组的维度，还可以使用 T 属性。。\n",
    "\n",
    ">例如有个 m 行 n 列的矩阵，使用 t() 函数就能转换为 n 行 m 列的矩阵。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 282,
   "id": "23428280-7753-43ee-8214-e8900900490e",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(array([[ 0,  1,  2,  3],\n",
       "        [ 4,  5,  6,  7],\n",
       "        [ 8,  9, 10, 11]]),\n",
       " array([[ 0,  4,  8],\n",
       "        [ 1,  5,  9],\n",
       "        [ 2,  6, 10],\n",
       "        [ 3,  7, 11]]))"
      ]
     },
     "execution_count": 282,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a = np.arange(12).reshape(3,4)\n",
    "a, a.T"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "13a233f7-e1e7-4352-bebc-d87708325436",
   "metadata": {},
   "source": [
    "## matlib.empty()\n",
    "\n",
    ">matlib.empty() 函数返回一个新的矩阵，语法格式为：\n",
    "\n",
    "`numpy.empty(shape, dtype, order)`\n",
    "\n",
    "*    shape: 定义新矩阵形状的整数或整数元组\n",
    "*    Dtype: 可选，数据类型\n",
    "*    order: C（行序优先） 或者 F（列序优先）"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 283,
   "id": "83a05f03-8f7d-4d7d-ab59-df69583b815f",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[2., 4.],\n",
       "       [6., 8.]])"
      ]
     },
     "execution_count": 283,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.empty((2,2))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "61daf372-47f7-44a7-85fb-b599d06f3acf",
   "metadata": {},
   "source": [
    "## numpy.matlib.zeros()\n",
    "\n",
    ">numpy.matlib.zeros() 函数创建一个以 0 填充的矩阵。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 284,
   "id": "c41d0720-13ba-4e44-8d36-b5bc9140cc70",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[0., 0.],\n",
       "       [0., 0.]])"
      ]
     },
     "execution_count": 284,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.zeros((2,2))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "13f3f677-1987-4dba-aba8-42476453b820",
   "metadata": {},
   "source": [
    "## numpy.matlib.ones()\n",
    "\n",
    ">numpy.matlib.ones()函数创建一个以 1 填充的矩阵。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 285,
   "id": "424548d6-efcc-47e6-b579-00b14160cede",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[1., 1.],\n",
       "       [1., 1.]])"
      ]
     },
     "execution_count": 285,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.ones((2,2))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e72540c4-d040-41cd-98a3-7dc1eff872c4",
   "metadata": {},
   "source": [
    "## numpy.matlib.eye()\n",
    "\n",
    ">numpy.matlib.eye() 函数返回一个矩阵，对角线元素为 1，其他位置为零。\n",
    "\n",
    "`numpy.matlib.eye(n, M,k, dtype)`\n",
    "\n",
    "*    n: 返回矩阵的行数\n",
    "*    M: 返回矩阵的列数，默认为 n\n",
    "*    k: 对角线的索引\n",
    "*    dtype: 数据类型"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 286,
   "id": "2b63346e-e9ef-4f62-a99f-5cc24f2e2835",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[0., 1., 0., 0.],\n",
       "       [0., 0., 1., 0.],\n",
       "       [0., 0., 0., 1.]])"
      ]
     },
     "execution_count": 286,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.eye(3, M=4, k=1, dtype=float)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7ccc307b-d822-488c-a3b9-246970f4dd6e",
   "metadata": {},
   "source": [
    "## numpy.matlib.identity()\n",
    "\n",
    ">numpy.matlib.identity() 函数返回给定大小的单位矩阵。\n",
    "\n",
    ">单位矩阵是个方阵，从左上角到右下角的对角线（称为主对角线）上的元素均为 1，除此以外全都为 0。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 287,
   "id": "aeb5b3b1-0452-4233-b1d8-4284e2abf7c3",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[1., 0., 0., 0., 0.],\n",
       "       [0., 1., 0., 0., 0.],\n",
       "       [0., 0., 1., 0., 0.],\n",
       "       [0., 0., 0., 1., 0.],\n",
       "       [0., 0., 0., 0., 1.]])"
      ]
     },
     "execution_count": 287,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.identity(5, dtype=float)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "794f194b-0298-474c-81b4-7779abb0b5a2",
   "metadata": {},
   "source": [
    "## numpy.matlib.rand()\n",
    "\n",
    ">numpy.matlib.rand() 函数创建一个给定大小的矩阵，数据是随机填充的。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 288,
   "id": "80044923-a258-49b3-8b44-c6ec841cc62e",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "matrix([[0.31637788, 0.00306015, 0.12529839],\n",
       "        [0.24379559, 0.08189208, 0.98578827],\n",
       "        [0.11256874, 0.41688846, 0.4765616 ]])"
      ]
     },
     "execution_count": 288,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import numpy.matlib\n",
    "np.matlib.rand(3,3)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7b2ce63f-96c7-4c61-be0c-30e4b62ae46a",
   "metadata": {},
   "source": [
    ">矩阵总是二维的，而 ndarray 是一个 n 维数组。 两个对象都是可互换的。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 289,
   "id": "09499382-b267-4634-b56f-6b7a983113d9",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "matrix([[1, 2],\n",
       "        [3, 4]])"
      ]
     },
     "execution_count": 289,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "i = np.matrix('1,2;3,4')\n",
    "i"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 290,
   "id": "8d72b3b7-8b85-4ca8-9e94-3c2bc0cd74af",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[1, 2],\n",
       "       [3, 4]])"
      ]
     },
     "execution_count": 290,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "j = np.asarray(i)\n",
    "j"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 291,
   "id": "6d480853-abb4-4f8e-a806-408240c2eddc",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "matrix([[1, 2],\n",
       "        [3, 4]])"
      ]
     },
     "execution_count": 291,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "k = np.asmatrix (j)\n",
    "k"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8917c35e-c70c-4e0d-a0ed-6f79e0de7318",
   "metadata": {},
   "source": [
    "# 线性代数\n",
    "\n",
    ">NumPy 提供了线性代数函数库 linalg，该库包含了线性代数所需的所有功能\n",
    "\n",
    "函数|描述\n",
    "--:|:--\n",
    "dot|两个数组的点积，即元素对应相乘。\n",
    "vdot|两个向量的点积\n",
    "inner|两个数组的内积\n",
    "matmul|两个数组的矩阵积\n",
    "determinant|数组的行列式\n",
    "solve|求解线性矩阵方程\n",
    "inv|计算矩阵的乘法逆矩阵"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d3fdfdf8-048b-4218-9d99-8e15ff16fdaf",
   "metadata": {},
   "source": [
    "## numpy.dot()\n",
    "\n",
    ">numpy.dot() 对于两个一维的数组，计算的是这两个数组对应下标元素的乘积和(数学上称之为向量点积)；\n",
    "对于二维数组，计算的是两个数组的矩阵乘积；\n",
    "对于多维数组，它的通用计算公式如下，即结果数组中的每个元素都是：\n",
    "数组a的最后一维上的所有元素与数组b的倒数第二位上的所有元素的乘积和：\n",
    "\n",
    ">dot(a, b)[i,j,k,m] = sum(a[i,j,:] * b[k,:,m])。\n",
    "\n",
    "`numpy.dot(a, b, out=None)`\n",
    "\n",
    "*    a : ndarray 数组\n",
    "*    b : ndarray 数组\n",
    "*    out : ndarray, 可选，用来保存dot()的计算结果"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 292,
   "id": "365e50b9-413a-44a5-9b42-7ca07234cd22",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[37, 40],\n",
       "       [85, 92]])"
      ]
     },
     "execution_count": 292,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# [[1*11+2*13, 1*12+2*14],[3*11+4*13, 3*12+4*14]]\n",
    "a = np.array([[1,2],[3,4]])\n",
    "b = np.array([[11,12],[13,14]])\n",
    "np.dot(a,b)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "32d2aa87-9c91-4803-8d6d-f6393c97e3c5",
   "metadata": {},
   "source": [
    "## numpy.vdot()\n",
    "\n",
    ">numpy.vdot() 函数是两个向量的点积。\n",
    "如果第一个参数是复数，那么它的共轭复数会用于计算。\n",
    "如果参数是多维数组，它会被展开。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 293,
   "id": "f703bea3-70a4-4879-af8b-d460523ec630",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "130"
      ]
     },
     "execution_count": 293,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 1*11 + 2*12 + 3*13 + 4*14 = 130\n",
    "a = np.array([[1,2],[3,4]])\n",
    "b = np.array([[11,12],[13,14]])\n",
    "np.vdot(a,b)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8b32779e-0a39-4f93-a68b-66511e006b5f",
   "metadata": {},
   "source": [
    "## numpy.inner()\n",
    "\n",
    ">numpy.inner() 函数返回一维数组的向量内积。对于更高的维度，它返回最后一个轴上的和的乘积。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 294,
   "id": "a57c0dfa-a5bd-496c-b9a3-dbe9b57a28a0",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "2"
      ]
     },
     "execution_count": 294,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 等价于 1*0+2*1+3*0\n",
    "np.inner(np.array([1,2,3]),np.array([0,1,0]))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 295,
   "id": "6f8d2407-f9c9-476a-bde9-c9049df2cddd",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[35, 41],\n",
       "       [81, 95]])"
      ]
     },
     "execution_count": 295,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 1*11+2*12, 1*13+2*14 \n",
    "# 3*11+4*12, 3*13+4*14\n",
    "a = np.array([[1,2], [3,4]]) \n",
    "b = np.array([[11, 12], [13, 14]]) \n",
    "np.inner(a,b)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6e433649-e41f-464c-a65b-e5f9fbb4f8fc",
   "metadata": {},
   "source": [
    "## numpy.matmul\n",
    "\n",
    ">numpy.matmul 函数返回两个数组的矩阵乘积。 虽然它返回二维数组的正常乘积，但如果任一参数的维数大于2，则将其视为存在于最后两个索引的矩阵的栈，并进行相应广播。\n",
    "\n",
    ">另一方面，如果任一参数是一维数组，则通过在其维度上附加 1 来将其提升为矩阵，并在乘法之后被去除。\n",
    "\n",
    ">对于二维数组，它就是矩阵乘法"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 296,
   "id": "11764764-2ee2-4531-b9ea-c82a078f5c8d",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[4, 1],\n",
       "       [2, 2]])"
      ]
     },
     "execution_count": 296,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a = [[1,0],[0,1]]\n",
    "b = [[4,1],[2,2]]\n",
    "np.matmul(a,b)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 297,
   "id": "07f3e11f-a474-4664-8388-ab07d8b58b70",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([1, 2])"
      ]
     },
     "execution_count": 297,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a = [[1,0],[0,1]]\n",
    "b = [1,2]\n",
    "np.matmul(a,b)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 298,
   "id": "6ba3086e-f9bf-477c-b040-2270f25a3819",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([1, 2])"
      ]
     },
     "execution_count": 298,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.matmul(b,a)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 299,
   "id": "95d78384-0e3f-4d76-aaff-f91991e5c4fc",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[[ 2,  3],\n",
       "        [ 6, 11]],\n",
       "\n",
       "       [[10, 19],\n",
       "        [14, 27]]])"
      ]
     },
     "execution_count": 299,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a = np.arange(8).reshape(2,2,2)\n",
    "b = np.arange(4).reshape(2,2)\n",
    "np.matmul(a,b)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5b2da54f-03ab-41b6-b42d-f199cf49acfa",
   "metadata": {},
   "source": [
    "## numpy.linalg.det()\n",
    "\n",
    ">numpy.linalg.det() 函数计算输入矩阵的行列式。\n",
    "\n",
    ">行列式在线性代数中是非常有用的值。 它从方阵的对角元素计算。 对于 2×2 矩阵，它是左上和右下元素的乘积与其他两个的乘积的差。\n",
    "\n",
    ">换句话说，对于矩阵[[a，b]，[c，d]]，行列式计算为 ad-bc。 较大的方阵被认为是 2×2 矩阵的组合。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 300,
   "id": "e279b86e-ef47-45e0-99d8-49e3ab976f59",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "-2.0000000000000004"
      ]
     },
     "execution_count": 300,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a = np.array([[1,2], [3,4]]) \n",
    "np.linalg.det(a)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 301,
   "id": "08e2cff6-d3e2-4890-88ed-b8ce0d735f46",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(array([[ 6,  1,  1],\n",
       "        [ 4, -2,  5],\n",
       "        [ 2,  8,  7]]),\n",
       " -306.0)"
      ]
     },
     "execution_count": 301,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "b = np.array([[6,1,1], [4, -2, 5], [2,8,7]])\n",
    "b, np.linalg.det(b)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 302,
   "id": "e33277f4-8776-4bce-ae3e-9e3407a971c3",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "-306"
      ]
     },
     "execution_count": 302,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "6*(-2*7 - 5*8) - 1*(4*7 - 5*2) + 1*(4*8 - -2*2)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6ab86e24-2fcb-4caf-a3b2-3a0aacdbfc58",
   "metadata": {},
   "source": [
    "## numpy.linalg.solve()\n",
    "\n",
    ">numpy.linalg.solve() 函数给出了矩阵形式的线性方程的解。\n",
    "\n",
    ">考虑以下线性方程：\n",
    "\n",
    ">  x + y + z = 6\n",
    "\n",
    ">  2y + 5z = -4\n",
    "\n",
    ">  2x + 5y - z = 27\n",
    "\n",
    "![矩阵](http://localhost:8080/_media/knowledgeaccumulation:informationsystem:%E7%BA%BF%E6%80%A7%E6%96%B9%E7%A8%8B-%E7%9F%A9%E9%98%B5.jpg)\n",
    "\n",
    ">如果矩阵成为A、X和B，方程变为：\n",
    "\n",
    ">AX = B\n",
    "\n",
    ">或\n",
    "\n",
    ">X = A^(-1)B"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f37889b8-421e-4c76-b490-7be1832fd9a5",
   "metadata": {},
   "source": [
    "## numpy.linalg.inv()\n",
    "\n",
    ">numpy.linalg.inv() 函数计算矩阵的乘法逆矩阵。\n",
    "\n",
    ">逆矩阵（inverse matrix）：设A是数域上的一个n阶矩阵，若在相同数域上存在另一个n阶矩阵B，使得： AB=BA=E ，则我们称B是A的逆矩阵，而A则被称为可逆矩阵。注：E为单位矩阵。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 303,
   "id": "a2269ddf-43fa-425f-8ec9-3b830f931cc8",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(array([[1, 2],\n",
       "        [3, 4]]),\n",
       " array([[-2. ,  1. ],\n",
       "        [ 1.5, -0.5]]))"
      ]
     },
     "execution_count": 303,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "x = np.array([[1,2],[3,4]])\n",
    "y = np.linalg.inv(x)\n",
    "x, y"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 304,
   "id": "4402ec74-179a-4bd8-bbab-abb70bad8ab2",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[1., 0.],\n",
       "       [0., 1.]])"
      ]
     },
     "execution_count": 304,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.round(np.dot(x,y))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 305,
   "id": "b3698dee-ed94-4c3d-839b-79eededaa413",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(array([[ 1,  1,  1],\n",
       "        [ 0,  2,  5],\n",
       "        [ 2,  5, -1]]),\n",
       " array([[ 1.28571429, -0.28571429, -0.14285714],\n",
       "        [-0.47619048,  0.14285714,  0.23809524],\n",
       "        [ 0.19047619,  0.14285714, -0.0952381 ]]))"
      ]
     },
     "execution_count": 305,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a = np.array([[1,1,1],[0,2,5],[2,5,-1]])\n",
    "# a 的逆\n",
    "a, np.linalg.inv(a)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 306,
   "id": "10ebcb29-a191-4659-b793-8fe325139f7b",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(array([[ 6],\n",
       "        [-4],\n",
       "        [27]]),\n",
       " array([[ 5.],\n",
       "        [ 3.],\n",
       "        [-2.]]))"
      ]
     },
     "execution_count": 306,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "b = np.array([[6],[-4],[27]])\n",
    "# A^(-1)B\n",
    "b, np.linalg.solve(a,b)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 307,
   "id": "4d5af835-2e72-4124-93d4-6a86c2311049",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 5.],\n",
       "       [ 3.],\n",
       "       [-2.]])"
      ]
     },
     "execution_count": 307,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.dot(np.linalg.inv(a),b)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "02a1fd00-74e8-45ac-a761-60b7976543c4",
   "metadata": {},
   "source": [
    "# IO\n",
    "\n",
    ">Numpy 可以读写磁盘上的文本数据或二进制数据。\n",
    "\n",
    ">NumPy 为 ndarray 对象引入了一个简单的文件格式：npy。\n",
    "\n",
    ">npy 文件用于存储重建 ndarray 所需的数据、图形、dtype 和其他信息。\n",
    "\n",
    ">常用的 IO 函数有：\n",
    "\n",
    "*    load() 和 save() 函数是读写文件数组数据的两个主要函数，默认情况下，数组是以未压缩的原始二进制格式保存在扩展名为 .npy 的文件中。\n",
    "*    savez() 函数用于将多个数组写入文件，默认情况下，数组是以未压缩的原始二进制格式保存在扩展名为 .npz 的文件中。\n",
    "*    loadtxt() 和 savetxt() 函数处理正常的文本文件(.txt 等)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "150d72c7-5043-4d41-b0ef-934f1a277442",
   "metadata": {},
   "source": [
    "## numpy.save()\n",
    "\n",
    ">numpy.save() 函数将数组保存到以 .npy 为扩展名的文件中。\n",
    "\n",
    "`numpy.save(file, arr, allow_pickle=True, fix_imports=True)`\n",
    "\n",
    "*    file：要保存的文件，扩展名为 .npy，如果文件路径末尾没有扩展名 .npy，该扩展名会被自动加上。\n",
    "*    arr: 要保存的数组\n",
    "*    allow_pickle: 可选，布尔值，允许使用 Python pickles 保存对象数组，Python 中的 pickle 用于在保存到磁盘文件或从磁盘文件读取之前，对对象进行序列化和反序列化。\n",
    "*    fix_imports: 可选，为了方便 Pyhton2 中读取 Python3 保存的数据。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 308,
   "id": "213b76fa-57fd-464b-8b43-1cfbb4f662e9",
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "a = np.array([1,2,3,4,5])\n",
    "np.save('outfile.npy',a)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 309,
   "id": "71b6fe7d-ddb7-4fa2-b9a9-af83e8727304",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([1, 2, 3, 4, 5])"
      ]
     },
     "execution_count": 309,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "b = np.load('outfile.npy')\n",
    "b"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a12ecb86-5fe5-4d37-b44b-098a1b71cffc",
   "metadata": {},
   "source": [
    "## np.savez\n",
    "\n",
    ">numpy.savez() 函数将多个数组保存到以 npz 为扩展名的文件中。\n",
    "\n",
    "`numpy.savez(file, *args, **kwds)`\n",
    "\n",
    "*    file：要保存的文件，扩展名为 .npz，如果文件路径末尾没有扩展名 .npz，该扩展名会被自动加上。\n",
    "*    args: 要保存的数组，可以使用关键字参数为数组起一个名字，非关键字参数传递的数组会自动起名为 arr_0, arr_1, …　。\n",
    "*    kwds: 要保存的数组使用关键字名称。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 310,
   "id": "5935e872-a0e7-4ad0-a8fb-ddb7a2c6999e",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['sin_array', 'arr_0', 'arr_1']"
      ]
     },
     "execution_count": 310,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a = np.array([[1,2,3],[4,5,6]])\n",
    "b = np.arange(0, 1.0, 0.1)\n",
    "c = np.sin(b)\n",
    "np.savez(\"runoob.npz\", a, b, sin_array = c)\n",
    "r = np.load(\"runoob.npz\")  \n",
    "r.files"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 311,
   "id": "507a5120-4284-455a-a32f-4a1b4ea0e94f",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[1, 2, 3],\n",
       "       [4, 5, 6]])"
      ]
     },
     "execution_count": 311,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "r[\"arr_0\"]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 312,
   "id": "b260ecf5-4dd1-415d-bdd6-92a19ddae9c7",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([0. , 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9])"
      ]
     },
     "execution_count": 312,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "r[\"arr_1\"]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 313,
   "id": "cc196733-4802-4877-94a8-303dac9dab90",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([0.        , 0.09983342, 0.19866933, 0.29552021, 0.38941834,\n",
       "       0.47942554, 0.56464247, 0.64421769, 0.71735609, 0.78332691])"
      ]
     },
     "execution_count": 313,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "r[\"sin_array\"]"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b23b111e-26aa-4f00-8c19-b802a32805b5",
   "metadata": {},
   "source": [
    "## savetxt()\n",
    "\n",
    ">savetxt() 函数是以简单的文本文件格式存储数据，对应的使用 loadtxt() 函数来获取数据。\n",
    "\n",
    "`np.loadtxt(FILENAME, dtype=int, delimiter=' ')`\n",
    "\n",
    "`np.savetxt(FILENAME, a, fmt=\"%d\", delimiter=\",\")`\n",
    "\n",
    ">参数 delimiter 可以指定各种分隔符、针对特定列的转换器函数、需要跳过的行数等。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 314,
   "id": "5d8a43c7-dc6e-4860-9ff3-92994e3645d4",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([1., 2., 3., 4., 5.])"
      ]
     },
     "execution_count": 314,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a = np.array([1,2,3,4,5]) \n",
    "np.savetxt('out.txt',a) \n",
    "np.loadtxt('out.txt')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 315,
   "id": "9ed58aa4-ffc8-4ad3-8421-5fba5b8e1257",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([1., 2., 3., 4., 5.])"
      ]
     },
     "execution_count": 315,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.savetxt(\"out.txt\",a,fmt=\"%d\",delimiter=\",\")\n",
    "np.loadtxt(\"out.txt\",delimiter=\",\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "bc014176-ec61-4d90-b977-9014c4f206ee",
   "metadata": {},
   "source": [
    "# Matplotlib\n",
    "\n",
    ">Matplotlib 是 Python 的绘图库。 它可与 NumPy 一起使用，提供了一种有效的 MatLab 开源替代方案。 它也可以和图形工具包一起使用，如 PyQt 和 wxPython。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 316,
   "id": "40b19c7f-00f9-4c2e-8def-ef194723c8a7",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "x = np.arange(1,11)\n",
    "y =  x ** 2 * 2 + 3 * x +  5\n",
    "plt.title(\"Matplotlib demo\")\n",
    "plt.xlabel(\"x axis caption\")\n",
    "plt.ylabel(\"y axis caption\")\n",
    "plt.plot(x,y)\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 317,
   "id": "a47d6a85-4351-4043-bfa1-321898450597",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "image/png": "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MDCQ+vXrF1pXr149Tp48aVIi+zZ69GjGjBnDgAEDaNSoEU888QQvvvgiEydONDua3QsICAAgKSmp0PqkpKSC50qaipAUmWEYxMTEsGTJElavXk1oaKjZkexahw4d2L17N/Hx8QWPpk2b8vjjjxMfH4+jo6PZEe1Oq1atrrukxKFDh6hWrZpJiexbZmYmDg6FP+4cHR2xWq0mJZLfhIaGEhAQwKpVqwrWpaamsmXLFlq2bHlPMmhqTIosOjqaefPm8e233+Lp6Vkwj+vt7Y27u7vJ6eyPp6fndedneXh4UKlSJZ23ZZIXX3yR+++/n3feeYfHHnuMrVu38sknn/DJJ5+YHc0ude/enb///e9UrVqVBg0aEBcXx+TJk3n66afNjmYX0tPTOXLkSMHysWPHiI+Px8fHh6pVqzJixAjefvttateuTWhoKK+//jpBQUEF3ywrcYZIEQE3fMyZM8fsaPJ/HnjgAeOFF14wO4Zd+/77742GDRsarq6uRlhYmPHJJ5+YHclupaamGi+88IJRtWpVw83NzahRo4bxt7/9zcjOzjY7ml1Ys2bNDT8zBg8ebBiGYVitVuP11183/P39DVdXV6NDhw7GwYMH71k+XUdIRERE7JbOERIRERG7pSIkIiIidktFSEREROyWipCIiIjYLRUhERERsVsqQiJi17KystCXZ0Xsl4qQiNi1KVOm8M9//vO69XPnzmXcuHH3PpCI3FMqQiJi12JjY3UFbhE7pltsiIhdOnDgAK+99hqrV6/m6tWruLm5MXToUDp06GB2NBG5h1SERMQu+fr60rJlSw4cOEBoaCitWrXizJkzuLu74+3tzdWrV8nPz2f27NmkpKTw008/0a5dO7Nji0gx09SYiJQJ//nPfwgLCyMnJweAxMREfH192bNnzw239/X1xcXFhf79+7NmzRoGDBhAjRo16N+/P4mJiUydOpVRo0aRmJhInz597uVLEZF7SEVIRMqEJ554gurVq/Pee+8B8PLLL/Pcc8/d8vyfr7/+mv79+9+riCJigzQ1JiJlxj/+8Q+aNm1KaGgoW7Zs4ZNPPrnptqmpqezYsYN33nmHM2fO8OSTTxIREXHvwoqITdDd50WkTPnwww8ZNWoUK1euvOWJzzk5OXz33XcAvPDCC0ydOpX8/HyefPLJQucIlS9fXucIiZRhmhoTkTJlx44duLu7c/HixVtu5+LiQt++fenbty+enp707duXgIAAnSMkYmc0NSYiZcZPP/3Etm3bWL58OQMGDKBTp05UrFjxhtsmJSWxatUq4uPjOXPmDA0bNqRbt273OLGImE0jQiJSJmRkZDB06FCmT59O27Zt6d69O6NHj77p9gkJCRw6dIhWrVpRuXJl9uzZQ/fu3e9hYhGxBTpHSETKhBdffJGTJ0/yzTffAHD58mXCwsJYtGgRDzzwwC33DQsL48CBA2zcuJGHHnoIb2/vQs/rHCGRsktTYyJSJkyZMqXQso+PD+fPny/SMRwdHRk8eDCzZ88utP4vf/kLjo6Od51RRGyPRoRERETEbukcIREREbFbKkIiIiJit1SERERExG6pCImIiIjdUhESERERu6UiJCIiInZLRUhERETsloqQiIiI2C0VIREREbFbKkIiIiJit1SERERExG6pCImIiIjd+n+7x2ev5TwvGAAAAABJRU5ErkJggg==\n",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "zhfont1 = matplotlib.font_manager.FontProperties(fname=\"../MiSans-Normal.ttf\") \n",
    " \n",
    "x = np.arange(1,11) \n",
    "y =  2  * x +  5 \n",
    "plt.title(\"菜鸟教程 - 测试\", fontproperties=zhfont1) \n",
    " \n",
    "# fontproperties 设置中文显示，fontsize 设置字体大小\n",
    "plt.xlabel(\"x 轴\", fontproperties=zhfont1)\n",
    "plt.ylabel(\"y 轴\", fontproperties=zhfont1)\n",
    "plt.plot(x,y) \n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 318,
   "id": "48b12804-d9ec-4da6-87bb-218099611ae2",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'DejaVu Math TeX Gyre'"
      ]
     },
     "execution_count": 318,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a=sorted([f.name for f in matplotlib.font_manager.fontManager.ttflist])\n",
    "a[0]"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a91f79a9-4eca-491e-a09a-cdbddd73b384",
   "metadata": {},
   "source": [
    "> 作为线性图的替代，可以通过向 plot() 函数添加格式字符串来显示离散值。 可以使用以下格式化字符。颜色的缩写。\n",
    "\n",
    "字符|描述| |字符|颜色\n",
    "--:|:--|:--:|--:|:--\n",
    "'-'|实线样式| |'b'|蓝色\n",
    "'--'|短横线样式| |'g'|绿色\n",
    "'-.'|点划线样式| |'r'|红色\n",
    "':'|虚线样式| |'c'|青色\n",
    "'.'|点标记| |'m'|品红色\n",
    "','|像素标记| |'y'|黄色\n",
    "'o'|圆标记| |'k'|黑色\n",
    "'v'|倒三角标记| |'w'|白色\n",
    "'^'|正三角标记\n",
    "'&lt;'|左三角标记\n",
    "'&gt;'|右三角标记\n",
    "'1'|下箭头标记\n",
    "'2'|上箭头标记\n",
    "'3'|左箭头标记\n",
    "'4'|右箭头标记\n",
    "'s'|正方形标记\n",
    "'p'|五边形标记\n",
    "'*'|星形标记\n",
    "'h'|六边形标记 1\n",
    "'H'|六边形标记 2\n",
    "'+'|加号标记\n",
    "'x'|X 标记\n",
    "'D'|菱形标记\n",
    "'d'|窄菱形标记\n",
    "'&#124;'|竖直线标记\n",
    "'_'|水平线标记"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 319,
   "id": "3f6cca14-3422-4188-a151-417a81eae7db",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAkAAAAHHCAYAAABXx+fLAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjUuMywgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/NK7nSAAAACXBIWXMAAA9hAAAPYQGoP6dpAABDQklEQVR4nO3deXQUVf738U/TQBIhCWs2E5IIKKII/kCRJYoDsqgIhEXBJYDjGpSwKTjDJgij4yigCKOPAzwiw2ZgGBx1AANGBQSZKD5qZAkSIAFR6IYICXbu80f/0mOTBNOQpJPU+3VOH6hbt6q+Rc5Jf6iqe8tmjDECAACwkFr+LgAAAKCyEYAAAIDlEIAAAIDlEIAAAIDlEIAAAIDlEIAAAIDlEIAAAIDlEIAAAIDlEIAAAIDlEIAAVDlxcXEaPnx4ue5z+PDhiouL82qz2WyaNm2aZ3natGmy2Ww6fvx4uR67W7du6tatW7nuE8ClIQABFrJ48WLZbDbZbDZ9/PHHxdYbYxQTEyObzaY777zzoo4xa9YsrV279hIrvThHjhzRtGnTlJGR4ZfjA6g+CECABQUGBmrZsmXF2rds2aJDhw4pICDgovft7wA0ffr0MgegM2fO6I9//GPFFgWgSiIAARZ0++23a9WqVfrll1+82pctW6b27dsrIiLCT5VVrsDAQNWuXdvfZQDwAwIQYEFDhw7Vjz/+qA0bNnjaCgoKtHr1ag0bNqzEbV588UV17txZjRs3VlBQkNq3b6/Vq1d79bHZbMrLy9OSJUs8t9qKnuUper7m22+/1ZAhQxQSEqLGjRtr9OjROnv27G/WvH//fg0ePFiNGjXSZZddpptuuknvvvuuZ/3mzZt1ww03SJJGjBjhOf7ixYtL3ef5zwAVOX78+EXVKEmvv/66mjdvrqCgIN14441KT08vsV9+fr6mTp2qFi1aKCAgQDExMXrqqaeUn59frMZRo0Zp1apVat26tYKCgtSpUyft3r1bkvTXv/5VLVq0UGBgoLp166YDBw4UO9aqVavUvn17BQUFqUmTJrrvvvt0+PDhMp0PUFMRgAALiouLU6dOnfT3v//d0/bee+/J4XDonnvuKXGbuXPn6vrrr9ezzz6rWbNmqXbt2ho8eLBXCHnrrbcUEBCghIQEvfXWW3rrrbf0yCOPeO1nyJAhOnv2rGbPnq3bb79d8+bN08MPP3zBeo8eParOnTvrgw8+0OOPP67nnntOZ8+e1V133aU1a9ZIkq6++mo9++yzkqSHH37Yc/ybb77Z53+fi6lRkt5880098sgjioiI0AsvvKAuXbrorrvuUnZ2tle/wsJC3XXXXXrxxRfVt29fvfLKK+rfv79efvll3X333cX2m56ernHjxikpKUnTpk3TN998ozvvvFPz58/XvHnz9Pjjj2vChAnaunWrRo4c6bXt4sWLNWTIENntds2ePVsPPfSQUlNT1bVrV508edLnfxugxjAALGPRokVGktmxY4d59dVXTXBwsPn555+NMcYMHjzY3HrrrcYYY2JjY80dd9zhtW1RvyIFBQXm2muvNb/73e+82uvVq2eSkpKKHXvq1KlGkrnrrru82h9//HEjyXzxxReettjYWK99pKSkGEkmPT3d03bq1CkTHx9v4uLijMvlMsYYs2PHDiPJLFq0qNjxk5KSTGxsrFebJDN16tSLqvF8BQUFJiwszLRr187k5+d72l9//XUjydxyyy2etrfeesvUqlXL63yMMWbhwoVGkvnkk0+8agwICDBZWVmetr/+9a9GkomIiDBOp9PTPmnSJCPJ07eopmuvvdacOXPG02/9+vVGkpkyZUqp5wPUdFwBAixqyJAhOnPmjNavX69Tp05p/fr1pd7+kqSgoCDP30+cOCGHw6GEhATt2rXLp+MmJyd7LT/xxBOSpH/961+lbvOvf/1LN954o7p27eppq1+/vh5++GEdOHBAX3/9tU81VESNO3fu1LFjx/Too4+qbt26nvbhw4crNDTUq++qVat09dVXq1WrVjp+/Ljn87vf/U6SlJaW5tW/e/fuXkP4O3bsKEkaOHCggoODi7Xv37/fq6bHH39cgYGBnn533HGHWrVq5XX1DrAanv4DLKpp06bq0aOHli1bpp9//lkul0uDBg0qtf/69es1c+ZMZWRkeD2nYrPZfDpuy5YtvZabN2+uWrVqlfjsSpHvv//e8+X+a1dffbVn/bXXXutTHRVRY0nb1qlTR1dccYVX2549e/TNN9+oadOmJe7r2LFjXsvNmjXzWi4KVDExMSW2nzhxwqumq666qtgxWrVqVeJUCIBVEIAACxs2bJgeeugh5ebmqk+fPmrQoEGJ/dLT03XXXXfp5ptv1muvvabIyEjVqVNHixYtKnE4vS98DVD+UN41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Mf3444/lWisAAKi+qswVoMLCQt111106efKkPv744xL7HD9+XO3bt9d9992n5557rtR9LV++XJdddpni4+O1b98+PfPMM6pfv762bt0qewmPy+fn5ys/P9+z7HQ6FRMTwxUgAACqEV+uAFWZAPTYY4/pvffe08cff6zo6Ohi651Op2677TY1atRI69atU506dcq87/3796t58+bauHGjunfvXmz9tGnTNH369GLtBCAAAKqPancLbNSoUVq/fr3S0tJKDD+nTp1S7969FRwcrDVr1vgUfiTpiiuuUJMmTbR3794S10+aNEkOh8Pzyc7OvqjzAAAA1YNfR4EZY/TEE09ozZo12rx5s+Lj44v1cTqd6tWrlwICArRu3ToFBgb6fJxDhw7pxx9/VGQp84UHBAQwSgwAAAvx6xWg5ORkLV26VMuWLVNwcLByc3OVm5urM2fOSHKHn549eyovL09vvvmmnE6np4/L5fLsp1WrVlqzZo0k6fTp05owYYK2bdumAwcOaNOmTerXr59atGihXr16+eU8AQBA1eLXK0ALFiyQJHU7b3KDRYsWafjw4dq1a5e2b98uSWrRooVXn6ysLMXFxUmSMjMzPSPI7Ha7vvzySy1ZskQnT55UVFSUevbsqRkzZnCVBwAASKpCD0FXJcwDBABA9VPtHoIGAACoTAQgAABgOQQgAABgOQQgAABgOQQgAABgOQQgAABgOQQgAABgOQQgAABgOQQgAABgOQQgAABgOQQgAABgOQQgAABgOQQgAABgOQQgAABgOQQgAABgOQQgAABgOQQgAABgObX9XQAAABXF5ZLS06WcHCkyUkpIkOx2f1eFqoAABACokVJTpdGjpUOH/tsWHS3NnSslJvqvLlQN3AIDANQ4qanSoEHe4UeSDh92t6em+qcuVB0EIABAjeJyua/8GFN8XVFbSoq7H6yLAAQAqFHS04tf+fk1Y6TsbHc/WBcBCABQo+TklG8/1EwEIABAjRIZWb79UDMRgAAANUpCgnu0l81W8nqbTYqJcfeDdRGAAAA1it3uHuouFQ9BRctz5jAfkNURgAAANU5iorR6tXT55d7t0dHuduYBAhMhAgBqpMREqV8/ZoJGyQhAAIAay26XunXzdxWoirgFBgAALIcABAAALIcABAAALIcABAAALIcABAAALIcABAAALIcABAAALMevAWj2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7mHDhpnbbrvNq8+ECRNM69atPcuxsbHmvvvu8ywXFhaasLAws2DBgjLXD6B03AIDcNFefPFF/fLLL1q1apXefvttBQQEXLD/ihUr1KVLF0VERKh+/fr64x//qIMHD3r1GTx4sAYMGKA//elPevHFF9WyZctS9/fkk09q5syZ6tKli6ZOnaovv/yy1L4ZGRmy2+265ZZbSu0zf/58tW/fXk2bNlX9+vX1+uuvF6uvbdu2uuyyyzzLnTp10unTp5WdnX3Bc/+1b775Rl26dPFq69Kli/bs2SOXy+Vpu+666zx/t9lsioiI0LFjx8p8HAClIwABuGj79u3TkSNHVFhYqAMHDlyw79atW3Xvvffq9ttv1/r16/Wf//xHf/jDHzzPzxT5+eef9fnnn8tut2vPnj0X3Ofvf/977d+/X/fff792796tDh066JVXXimxb1BQ0AX3tXz5co0fP14PPvig/v3vfysjI0MjRowoVl9lqlOnjteyzWZTYWGhn6oBahYCEICLUlBQoPvuu0933323ZsyYod///vcXvDrx6aefKjY2Vn/4wx/UoUMHtWzZUt9//32xfuPGjVOtWrX03nvvad68efrwww8vWEdMTIweffRRpaamaty4cXrjjTdK7NemTRsVFhZqy5YtJa7/5JNP1LlzZz3++OO6/vrr1aJFC+3bt69Yvy+++EJnzpzxLG/btk3169dXTEyMJPeIr19fxSnJ1VdfrU8++aTY8a+88krZ7fYLbgugfBCAAFyUP/zhD3I4HJo3b55ndNfIkSNL7d+yZUsdPHhQy5cv1759+zRv3jytWbPGq8+7776rv/3tb3r77bd12223acKECUpKStKJEydK3GdKSoo++OADZWVladeuXUpLS9PVV19dYt+4uDglJSVp5MiRWrt2rbKysrR582atXLnSU9/OnTv1wQcf6LvvvtPkyZO1Y8eOYvspKCjQgw8+qK+//lr/+te/NHXqVI0aNUq1atXyHGf79u06cOCAjh8/XuIVm3HjxmnTpk2aMWOGvvvuOy1ZskSvvvqqxo8fX+q/H4By5u+HkABUP2lpaaZ27domPT3d05aVlWVCQkLMa6+9Vup2EyZMMI0bN/aMpHr55ZdNaGioMcaYY8eOmfDwcDNr1ixP/4KCAtO+fXszZMgQz3H1q4eJR40aZZo3b24CAgJM06ZNzf3332+OHz9e6vHPnDljxowZYyIjI03dunVNixYtzN/+9jdjjDFnz541w4cPN6GhoaZBgwbmscceMxMnTjRt27b1bJ+UlGT69etnpkyZ4jmPhx56yOvh78zMTHPTTTeZoKAgI8lkZWUVq9sYY1avXm1at25t6tSpY5o1a2b+/Oc/e9UaGxtrXn75Za+2tm3bmqlTp5Z6fgDKjpmgAaCMhg8frpMnT2rt2rX+LgXAJeIWGAAAsBwCEAAAsBxugQEAAMvhChAAALAcAhAAALAcAhAAALAcAhAAALAcAhAAALAcAhAAALAcAhAAALAcAhAAALAcAhAAALCc/w8eh26o216YXwAAAABJRU5ErkJggg==\n",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "x = np.arange(1,11) \n",
    "y =  2  * x +  5 \n",
    "plt.title(\"Matplotlib demo\") \n",
    "plt.xlabel(\"x axis caption\") \n",
    "plt.ylabel(\"y axis caption\") \n",
    "plt.plot(x,y,\"ob\") \n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "071c38dc-b482-4742-9bad-dea21ae89be9",
   "metadata": {},
   "source": [
    "## 绘制正弦波\n",
    "\n",
    ">以下实例使用 matplotlib 生成正弦波图。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 320,
   "id": "70e31e61-548b-4068-af98-2f3fdfc78c04",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "x = np.arange(0,  3  * np.pi,  0.1)\n",
    "y = np.sin(x)\n",
    "plt.title(\"sine wave form\")\n",
    "plt.plot(x, y)\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5dead516-02fb-4a86-a4fb-c1a5da75bf50",
   "metadata": {},
   "source": [
    "## subplot()\n",
    "\n",
    ">subplot() 函数允许你在同一图中绘制不同的东西。\n",
    "\n",
    ">以下实例绘制正弦和余弦值"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 321,
   "id": "5be9f6ee-5322-4238-9325-bdba42421838",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAi8AAAGzCAYAAADnmPfhAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjUuMywgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/NK7nSAAAACXBIWXMAAA9hAAAPYQGoP6dpAAB8gUlEQVR4nO3dd3xT9f7H8VeS7k0HLaUtlFlGacuUoYIiiIhMZV6GAlcFBcFBVUBEQFAUBUTBAQoIIiBTFBmibAqFsimzULoobbpHcn5/FHp/KJumJ+PzfDzyuI+Gk+bdXNu8c853aBRFURBCCCGEsBBatQMIIYQQQtwLKS9CCCGEsChSXoQQQghhUaS8CCGEEMKiSHkRQgghhEWR8iKEEEIIiyLlRQghhBAWRcqLEEIIISyKlBchhBBCWBQpL0IIs1S1alUGDhyodgwhhBmS8iKEKHdxcXH06NGDKlWq4OTkROXKlXniiSeYOXOm2tGEEBZAI3sbCSHK044dO2jTpg0hISEMGDCAgIAAEhIS2LVrF6dPnyY+Ph6AgoICtFot9vb2KicWQpgbKS9CiHLVsWNH9u7dy8mTJ/Hy8rrh31JSUqhYsaI6wYQQFkMuGwkhytXp06epV6/ev4oLcENx+eeYl/nz56PRaNi+fTujRo3Cz88PV1dXunbtSmpq6r++16+//srDDz+Mq6sr7u7udOzYkSNHjpjiRxJClDMpL0KIclWlShViYmI4fPjwfT3+lVde4eDBg4wfP56XXnqJNWvWMHz48BuO+eGHH+jYsSNubm5MnTqVsWPHcvToUVq1asW5c+fK4KcQQqjJTu0AQgjb8vrrr9OhQwciIyNp2rQpDz/8MI8//jht2rS5q/EtPj4+/P7772g0GgCMRiOff/45mZmZeHp6kp2dzauvvsrgwYOZO3du6eMGDBhA7dq1mTx58g33CyEsj5x5EUKUqyeeeIKdO3fyzDPPcPDgQaZNm0b79u2pXLkyq1evvuPjhw4dWlpcAB5++GEMBgPnz58HYOPGjWRkZNC7d2/S0tJKbzqdjmbNmrFlyxaT/WxCiPIhZ16EEOWuSZMmrFixgsLCQg4ePMjKlSv59NNP6dGjB7GxsdStW/eWjw0JCbnh6woVKgBw9epVAE6dOgXAY489dtPHe3h4lMWPIIRQkZQXIYRqHBwcaNKkCU2aNKFWrVoMGjSIZcuWMX78+Fs+RqfT3fT+6xMnjUYjUDLuJSAg4F/H2dnJnz0hLJ38FgshzELjxo0BuHz58gN9n+rVqwMlM5fatm37wLmEEOZHxrwIIcrVli1buNnyUuvXrwegdu3aD/T927dvj4eHB5MnT6aoqOhf/36zadVCCMsiZ16EEOXqlVdeITc3l65duxIWFkZhYSE7duxg6dKlVK1alUGDBj3Q9/fw8GDOnDn85z//oWHDhvTq1Qs/Pz8uXLjAunXraNmyJbNmzSqjn0YIoQYpL0KIcvXxxx+zbNky1q9fz9y5cyksLCQkJISXX36Zd99996aL192rPn36EBgYyIcffshHH31EQUEBlStX5uGHH37gciSEUJ9sDyCEEEIIiyJjXoQQQghhUaS8CCGEEMKiSHkRQgghhEWR8iKEEEIIiyLlRQghhBAWRcqLEEIIISyK1a3zYjQaSUxMxN3d/YadZ4UQQghhvhRFISsri8DAQLTa259bsbrykpiYSHBwsNoxhBBCCHEfEhISCAoKuu0xVlde3N3dgZIf3sPDQ+U0QgghhLgber2e4ODg0vfx27G68nL9UpGHh4eUFyGEEMLC3M2QD5MO2N22bRudOnUiMDAQjUbDL7/8csfHbN26lYYNG+Lo6EiNGjWYP3++KSMKIYQQwsKYtLzk5OQQERHB7Nmz7+r4s2fP0rFjR9q0aUNsbCwjR45k8ODB/Pbbb6aMKYQQQggLYtLLRh06dKBDhw53ffyXX35JaGgo06dPB6BOnTr8/ffffPrpp7Rv395UMYUQQghhQcxqzMvOnTtp27btDfe1b9+ekSNH3vIxBQUFFBQUlH6t1+tNFU/chNGocCE9lyOJeo5ezuRqbhEFRUbyiw0UFBkpNBjxdXMgqIILQRWcCargTBUfVwI9nWQquxBCFVeyCziVks2plGzik7NIzy3CqCgoioKigFFR8HFzpJqvK9X93Kjm50pQBRd0WvmbZS7MqrwkJSXh7+9/w33+/v7o9Xry8vJwdnb+12OmTJnChAkTyiuiAE4kZbHmYCJ7zqZz9LKe7ILie/4eId4uPFrLj9a1/Whe3QcXB7P6T1EIYUWy8ovYciKVDYcvs/tMOldyCu/5ezjYaWlStQJP1PHniXoBVPb69/uRKD8W/44RHR3NqFGjSr++PtVKlK2E9FxWH0xkdWwiJ5Kzbvg3BzstYQHu1Av0IMDDGUd7LU52WhztddhpNaRkFXDxah4Xr+Zy6WoeF9JzuZCeyw+7zvPDrvM46LQ8VN2Hfs1CeLyOv3y6EUI8sJyCYtbFXea3w0n8dSqNQoPxhn8P9namZkV3alZ0w9/DCa0GtFoN1//6JOsLOJOWzZnUHM6k5VBYbGR7/BW2x1/hvTVHqRfoQbu6AfRsEkyAp1P5/4A2zqzKS0BAAMnJyTfcl5ycjIeHx03PugA4Ojri6OhYHvFsUsz5dGb8cYq/TqWV3ueg0/JobT/a1fUnPMiT6n5u2Ovufux3TkExO09fYevJFLaeSOXi1Ty2nUxl28lUqvi4MLBFVZ5tHIybo1n95ymEsAAZuYUs2HGe73acJSO3qPT+an6udKgfwON1/AkLcL+ns70Go8LZtBy2HE/h96NJxJy/ypFEPUcS9czacoquUZUZ+kh1alR0M8WPJG5CoyiKUi5PpNGwcuVKunTpcstj3nrrLdavX09cXFzpfX369CE9PZ0NGzbc1fPo9Xo8PT3JzMyUdV4eQMz5q8z442RpadFqoHl1H56JCOTJepXwdLEvk+dRFIXTqTn8HHORH/dcIDOv5I+Nu6MdfR4KYVibGng4lc1zCSGsV4o+n2/+PsvCXefJKTQAUMXHhW5RQXQID6BmRbcyG2d3JbuATcdT+HnfRfacSwdAo4En6vjzYuvqNAypUCbPY2vu5f3bpOUlOzub+Ph4AKKiovjkk09o06YN3t7ehISEEB0dzaVLl/j++++BkqnS9evXZ9iwYTz//PNs3ryZV199lXXr1t31bCMpLw/meJKeyeuPs+1kKgA6rYYeDYMY/lgNgr1dTPrcuYXFLN9/ie+2n+VMag4Avm6OvPVkbbo3DEIrl5OEEP9QUGzgqz/PMGtLPIXFJZeGwgLcGdamBk+FVzL5ZeiY81f56s/T/H70f1cNukQG8k7Huvi5y1WBe2E25WXr1q20adPmX/cPGDCA+fPnM3DgQM6dO8fWrVtveMxrr73G0aNHCQoKYuzYsQwcOPCun1PKy/0pKDYwe8tpvtgST7FRQafV0L1hZYa3qUmIj2lLyz8ZjQqbj6cwef0xzqSVlJjIYC8mPFOPiGCvcs0ihDBfu89c4e2VcZy+9mGnYYgXwx+rQZvaFct9NmN8SjZf/Xman/dfRFHA3cmON9vXpk+zKjKO7y6ZTXlRg5SXe3fgwlXeWn6Ik8nZALSt48+4p+uWe2n5p8JiI99tP8vnm06RU2hAo4F+zarwTsc6ONnrVM0mhFBPRm4hU9YfZ+m+BAB83RwY16kenRpUUn0JhkMXM3hn5WHiLmUCEBHkyaSu4dSv7KlqLksg5UXKy13JLzLw8W8n+Gb7WRQFfFwdmNC5Hh3D1f8D8P8l6/P58NfjrDxwCYDa/u7M6hNFTf87b94lhLAu2+PTGLHkAGnZJdOdezcNYcyTYWU2Dq8sGIwKi3af56MNJ8gqKMZOq2FMhzBeaBVqVn9bzY2UFykvd3QpI48Xf4gp/XTQLaoyY5+uSwVXB5WT3dpfp1J5belB0rILcLLX8l6nevRsEix/DISwAUajwuwt8Xzyx0kUBWpWdGNKt3AaV/VWO9otpWTl897qI6yPSwLgibr+fNwjwqyKljmR8iLl5bZ2xKcx/McDpOcUUsHFnunPRfBYmP+dH2gGUrMKGPVTbOksqKcbVGJyt3CZkSSEFcvILeS1pbFsOVEykaBn42AmdK5nEZePFUVh4e4LTFxzlEKDkWBvZ2b3aUiDIC+1o5kdKS9SXm5KURS+/ussU349hlGBeoEefNmvkclnEZU1o1Fh7l9n+Pi3ExQbFWpWdOO7QU0IqmBZP4cQ4s4OXczgpYX7uZSRh6Odlold6vNcY8tbiDTuYiYvL44hIT0PB52W8c/UpW+zKmrHMitSXqS8/Et+kYE3fj7EmoOJAHRrWJnJXcMt4pPLrRy4cJWXFu4nSZ+Pn7sj3w5oQniQDIoTwlr8cTSZYYv3U1BspIqPC1/0bUi9QMv9Hc/MK+KNZQdLp1UPa1Od19vVlkvf10h5kfJyg6z8IoZ+H8POM1ew02oY+3Rd+jevYhW/MJcz8xj03V6OJ2Xh4qBjVp8oi7kEJoS4tZ/2JhC9Mg6DUaF1bT8+6xWFp7PlXx5WFIWZm+P5ZONJAHo0CmJKt/B7WqXcWt3L+7e8WlbuSnYBfebtZueZK7g52vH9C00Z0KKqVRQXgEqezix7sTkP1/Qlt9DA4AX7+GHXebVjCSHuk6KUDMx9c/khDEaFHo2CmNe/sVUUFyhZbf7Vx2syrXsDdFoNP8dcZPCCfeTcxwa3tkzKixVLzMjj2a92EncpE29XB34c8hAtqvuqHavMuTvZ8+3AJjzbKAijAmN/Ocznm06pHUsIcY8MRoX3Vh/ho99OAPBy6+p81KOBVZ6VeK5JMPP6N8LZXsefJ1PpPW8XadkFaseyGNb3X4QASlZ77DFnB2dScwj0dOKn/za36vEg9jot03o04LW2tQD4ZONJPvtDCowQlsJgVBj9UywLdp5Ho4Hxnery5pNhVnOW+GYeC/Pnx6EP4e3qwKGLmfSeKwXmbkl5sUKnU7PpNXcniZn5VPNzZdlLLWxit1ONRsOItjUZ0yEMgE//kAIjhCUwGhXeWn6IX2ITsdNq+KxXFINahqodq1xEBnux/KUWVPJ04lRKNv2+3k16TqHascyelBcrk5CeS995u0nLLqRuJQ+W/bc5lb2c1Y5Vrl58tLoUGCEshKIovPPLYX6OuYhOq2FWnyieiQhUO1a5CvV1ZfGQh6jo7sjxpCz6fb2bjFwpMLcj5cWKJOvz6fv1bpL0+dSo6MYPLzTFx802dzX9Z4GZ8cdJlRMJIf5JURQmrDnKj3suoNXApz0jebJ+JbVjqeJ6gfF1c+ToZT3/+WYPmXlFascyW1JerMSV7AL6fr2bC+m5hHi7sGhwM5stLtf9/wIz449TfPP3WZUTCSGuUxSFKb8eZ/6Oc2g0MK1HhM2dcfmnGhXdWDykGT6uDsRdyqT/t3vIypcCczNSXqxAZl4R//lmD/Ep2VTydGLR4Gb4ezipHcssvPhodd5oXxuAiWuPli7SJ4RQ18zN8czddgaAyV3D6dEoSOVE5qGWvzsLBzfDy8WegwkZvLgwhsJio9qxzI6UFwtXUGxg8IK9HL2sx9fNgUWDm1nccv+m9nLr6gxoXrIM9+ifDrLjdJrKiYSwbctjLpYu0vZep7r0bhqiciLzUqeSBz883wwXBx3b468wZsUhrGw92Qcm5cWCKYrCmz8fYu+5q7g72fHDC82o5mf9s4rulUajYVynejwVHkChwch/v4/h2GW92rGEsEnb49N4a/khoOTM6EAbmVV0r8KDPPmib0N0Wg0r9l8qLXuihJQXC/bpH6dYdW1q4Zf9GlGnkmyHcCs6rYZPnoukaag3WQXFDPxuD5cy8tSOJYRNOZGUxYs/xFBsVOgUEcib1y7piptrXbsik7vWB0ous/2454LKicyHlBcLtTzmYukqspO7htOyhvWtnFvWnOx1zPtPY2r5u5GsL2DAt3vQy2A4IcpFsj6fQd/tIaugmKZVvfn42QZotda7AF1Z6dkkhFcfqwHAu78cZsuJFJUTmQcpLxZo5+mSa6BQMp7juSaWtz28Wjxd7FnwfFMCPJyIT8lm5JJYDEa5liyEKeUUFDPou72lC2fO7d8IRzvL3dG+vL32RC26NwzCYFQYtmi/XPZGyovFOZ2azYsLYygyKHRsUInX28lp13tVydOZef0b42inZfPxFD7+/YTakYSwWoqiMPqngxy9rMfH1YH5A5vi5eKgdiyLotFomNItnFY1SjagHfrDPq7a+Cq8Ul4sSFZ+EUO/30dmXhENQ7yY/myEnHa9T+FBnkzr0QCAOVtPsyr2ksqJhLBOX2w9zYYjSdjrNMzt35gQH5kNeT8c7LTM6hNFiLcLCel5DP9xP8UG251CLeXFQiiKwuvLDnI6NYcADye++k9jnOzltOuD6BxZmRcfrQ7Amz8fIu5ipsqJhLAuW/7fmc33O9enUZUKKieybF4uDszt36h0CvWHvx5XO5JqpLxYiDl/nua3I8k46LTM6dcQP3fbXj23rLzRvjaPhVWkoNjI0B/2kZolO7oKURbOpeXw6pIDKAr0aRYia7mUkbAAD6Y/GwHA13+fZeWBiyonUoeUFwuw7WQqH/9W8ullQud6RIXIp5eyotNqmNErkup+rlzOzOflRTEU2fCpWCHKQnZBMUN/2EdWfjENQ7wY36mu2pGsSofwSrxybQbSmOVxNnnWWMqLmUtIz+XVJQcwKtCrSbB8ejEBDyd75vVvjLujHXvPXZUBvEI8AEVReGPZQU4mZ1PR3ZEv+8nMIlN4rW0tHr921vi/NjiAV8qLGcsvMvDiwhgycouICPLkvWfqqR3JalXzcysdwPvVn2fYdCxZ5URCWKZvt5/j18MlA3Tn9GtERdlnzSS0Wg2f9ook1NeVxMx8Ri87iNGGln2Q8mLGJqw5ypHEkumFc/o1kgG6JtYhvBKDWlYFYNRPB7l4NVfdQEJYmIMJGXz46zEAxj5dVwbompiHkz2z+zTE4dqyD1//fUbtSOVGyouZWnsokR/3XECjgRm9Ign0clY7kk2I7lCHiGAvMvOKGLb4gOzmKsRdyswrYviP+ykyKHSoH8B/HqqidiSbUDfQg/c6lZyVn7rhBDHnr6qcqHyUS3mZPXs2VatWxcnJiWbNmrFnz55bHjt//nw0Gs0NNycn2zrteOFKLtHL44CSFXQfrumnciLb4WCnZVbvKDydS7ajn3LtU6QQ4tYURWHM8kMkpOcR7O3Mh90boNHIGlTlpXfTYDpFBGIwKryyeD8ZudY//sXk5WXp0qWMGjWK8ePHs3//fiIiImjfvj0pKbfen8HDw4PLly+X3s6fP2/qmGajsNjIKz/uJ6ugmEZVKvBa21pqR7I5wd4ufPJcyVTE77af49e4yyonEsK8Ldx1vnScy6zeDfF0tlc7kk3RaDRM7lr/f+NffjqIolj3+BeTl5dPPvmEIUOGMGjQIOrWrcuXX36Ji4sL33777S0fo9FoCAgIKL35+/vf8tiCggL0ev0NN0v28e8nOHgxE09nez7vHYWdTq7sqeHxOv7899FqALy1/BCJsgO1EDd1+FImE9eWnKF868kwIoK91A1ko9yd7JnVJwoHOy2bjqfw9V9n1Y5kUiZ9ZywsLCQmJoa2bdv+7wm1Wtq2bcvOnTtv+bjs7GyqVKlCcHAwnTt35siRI7c8dsqUKXh6epbegoMtd5PCLSdSmLutZMDVtB4NqCzjXFT1ervaRAR5os8v5rWlsoGjEP+UU1DMKz8eoNBgpG0df15oFap2JJtWL9CTcU+XrKkz7bfjHL5kveu/mLS8pKWlYTAY/nXmxN/fn6SkpJs+pnbt2nz77besWrWKhQsXYjQaadGiBRcv3nwVwejoaDIzM0tvCQkJZf5zlIcUfcmpPoCBLarSvl6AyomEvU7LZ72icHHQsftsOl9tO612JCHMygfrjnI2LYdKnk58/KyMczEHfZuF8GS9AIoMCiOWHCCv0KB2JJMwu2sSzZs3p3///kRGRvLoo4+yYsUK/Pz8+Oqrr256vKOjIx4eHjfcLI2iKLy5/BDpOYXUreTBmA5hakcS11T1dS1dX+eT309y6GKGuoGEMBO/H0nixz0JaDQw/bkI2SnaTFzfgbqiuyOnU3OYvN46Jx2YtLz4+vqi0+lITr5xwa/k5GQCAu7uzIK9vT1RUVHEx8ebIqJZWLj7AltPpOJgp+WzXpGynouZebZREE+FB1BsVBixJJbcwmK1IwmhqpSsfMasKJkROeTharSo7qtyIvH/VXB1YPq1SQc/7DrPluO3niBjqUxaXhwcHGjUqBGbNm0qvc9oNLJp0yaaN29+V9/DYDAQFxdHpUqVTBVTVadTs5m07igAY54Mo6a/u8qJxD+VjOQPp5KnE2fTcnh/zVG1IwmhGkVRePPnkjPFYQHujG4nMyLN0cM1/Xi+ZckYpDd+PkhatnVtOmvyy0ajRo1i3rx5LFiwgGPHjvHSSy+Rk5PDoEGDAOjfvz/R0dGlx7///vv8/vvvnDlzhv3799OvXz/Onz/P4MGDTR213BUZjLy2NJb8IiOtavgysEVVtSOJW/ByceCT5yLRaGDJ3gQ2HL75mC0hrN0Pu86Xnin+vHeU7Ftkxt58sja1/d1Jyy7krZ8PWdX0aZOXl549e/Lxxx8zbtw4IiMjiY2NZcOGDaWDeC9cuMDly/9bR+Pq1asMGTKEOnXq8NRTT6HX69mxYwd161rfrqQzN8dz6GImHk52fPRsA7RaGexmzppX9+G/j1QH4J2VcVyxsk8yQtxJfEoWk9aVjKGI7hBGLTlTbNac7HXM6BWJg65k+vSi3RfUjlRmNIo1VTFAr9fj6elJZmamWQ/e3X/hKs9+uRODUWFm7yg6RQSqHUnchYJiA51nbed4UhZP1gtgTr+GMsNC2IQig5FuX+wg7lImD9f0ZcGgpvKBy0J8/dcZPlh3DBcHHRtGPEKIj4vakW7qXt6/zW62kS3ILSxm1LV1QzpHBkpxsSCOdjqmPxeBnVbDhiNJrD6YqHYkIcrFl1tPE3epZAHNj5+NkOJiQZ5vGUqzUG9yCw288bN17D4t5UUF0zac4NyVXAI8nHi/c32144h7VC/QkxGP1wRg7C+HSdbnq5xICNM6mqjn882nAJjwTD38PWxrvzlLp9Vq+KhHROmaVfN3nFM70gOT8lLOdp+5UvofztQeDWQPEAv1UuvqNLi2+u5by61rIJwQ/19hsZHRyw5SZFBoV9efzpFyptgShfi48PZTdYCS1XfPpGarnOjBSHkpR7mFxbzx8yEAejYO5tFaslu0pbLTaZn+bAQOdlq2nkhl6V7LXNlZiDuZtSWeY5f1VHCxZ1LXcBnjZcH6NguhVQ1f8ouMvL7soEVveSLlpRxN23CCC+m5BHo68c7TddSOIx5QTX933mhXG4CJa4+SkJ6rciIhytbhS5nM3lKyQOjELvXxc3dUOZF4EBqNhqk9GuDuaMf+Cxl8/dcZtSPdNykv5WTX/7tc9GH3Bng4yeUia/B8q1CaVK1ATqGBt1fGyeUjYTUKig2M/qnk03nH8Eo83UAuF1mDyl7OjL22eeP0jSc5lZylcqL7I+WlHOQUFPPmtctFvZsG84hcLrIaOq2Gqd0b4Gin5a9TaSzbd/MNRIWwNDM3xXMiOQtfNwcmdpGJBdbk2cZBtKntR2GxkTd+PmSRl4+kvJSDaRuOcyE9l8pezqUDpoT1qObnVrpE+sR1R0nKlNlHwrIdScxkzp8lu6h/0KU+3q6y6aI1Kdm8seTyUWxCBt9tP6t2pHsm5cXE9p5L5/td5wGY2r0B7nK5yCq90KoaEcFeZOUX845cPhIWrMhg5M1rn8Y7hlfiyfrWua+crQvwdOLtjiUfpj/+/QTnr+SonOjeSHkxofwiw7VptCWzi1rVlJ1XrZVOq+GjHg2w12nYdDxFFq8TFmvutjMcSdTj5WLPe8/UUzuOMKFeTYJpUd2H/CIjby0/ZFGL10l5MaHPN53iTGoOFd0dSxuusF61/N159bGSxevGrz5CapbsfSQsS3xKNp9tKlmMbtzTdWV2kZXTaDR82K0BzvY6dp1J58e9lrP3kZQXEzl8KZOvtpVMQ5vYpb4sRmcjXmxdnbqVPMjILWL86sNqxxHirhmNCm8tP0RhsZHWtf3oGlVZ7UiiHIT4uPB6+5IlH6asP05iRp7Kie6OlBcT+Oc14/b1AtSOJMqJvU7LtB4N0Gk1rI9L4rcjSWpHEuKufL/zHDHnr+LqoJPF6GzMwBZVaRjiRXaB5YzZk/JiAvP+OsPRy3o8neWasS2qX9mToY9UA2DcqsPo84tUTiTE7SWk5zLttxMAjHmqDpW9nFVOJMqTTqthWo8GOOi0bDmRyqpY8x+zJ+WljJ1OzWbGH3LN2NaNeLwmVX1cSNYXMPXX42rHEeKWFEXhnV8Ok1tooGmoN32bhqgdSaigRkV3Xn28BgDvrz1Kek6hyoluT8pLGTIaFaKXx1FYbOSRWn50ayjXjG2Vk72Oyd3CAVi0+wJ7zqarnEiIm1sVm8i2k6k42Gn5sFs4Wq1cLrJVQx+pTm1/d9JzCvlg3VG149yWlJcytHRfAnvOpeNsr2NSl/pyzdjGtajuS68mwQBErzhEfpFB5URC3Cg9p5D315a8Sb36WA2q+bmpnEioycFOy4fdw9FoYMX+S/x1KlXtSLck5aWMpOjzmbz+GACj29Ui2NtF5UTCHER3qIOfuyOnU3P44toGd0KYiw/WlVweqO3vztBHqqsdR5iBqJAKDGheFYC3V8aRV2ieH7qkvJSRCWuOkpVfTIMgTwa1DFU7jjATni72vH9t0PYXW09zPEmvciIhSvx1KpUV+y+h0cCH3cNxsJO3A1Hi9fa1CfR0IiE9j0//OKl2nJuS/1rLwB9Hk1kXdxmdVsOUbuHo5Jqx+H+erB9Au7r+FBsVxiyPs8hN0IR1ySs08M7KknWIBjSvSlRIBZUTCXPi5mjHB11LNuP8+q8zHL6UqXKif5Py8oCy8osYu6rkj8Dgh0OpF+ipciJhbjQaDe93ro/btU3QFu0+r3YkYeNm/HGSC+m5BHo6lS5QJsT/91iYP50iAjEq8NbyQxQbjGpHuoGUlwc0/feTXM7MJ8TbhZGP11I7jjBTAZ5OvPVkyZvEtA0nZOdpoZrDlzL5+u+SXYQndikp1ULczPhOdfF0tudIop7vtp9TO84NpLw8gAMXrrJg5zkAJnWtj7ODTt1Awqz1bVaFqGurWMrWAUINBqPC2ytLLl12bFCJx+v4qx1JmDFfN0feeapkX75PNp4kIT1X5UT/I+XlPhUZjESviENRoFtUZR6u6ad2JGHmtNfGRNlpNfx2JFm2DhDlbsGOcxy6mIm7kx3jO9VVO46wAM82DqJZqDd5RQbGrjpsNlsHSHm5T1//dZbjSVlUcLHn3aflj4C4O2EBHqVbB4xfdYQs2TpAlJNLGXl8/Pu1LQA6hFHR3UnlRMISaDQaJncLx0GnZeuJVNYeuqx2JEDKy325cCWXzzaVTB97p2NdvF0dVE4kLMmrj9ekio8LSfp8pv9untMQhXVRFIXxq0q2AGhcpQK9m8gWAOLuVfdzY1ibkq0DJqw5Smau+h+6pLzco5J9QOLILzLSoroP3WULAHGPnOx1TO5asnXAgp3nOHDhqsqJhLXbcDiJP46lYK8ruXQpWwCIe/Vi62pU93MlLbuADzccUztO+ZSX2bNnU7VqVZycnGjWrBl79uy57fHLli0jLCwMJycnwsPDWb9+fXnEvCurDyby16k0HOy0sm28uG8ta/jSrWFlFAWiV8RRZGbTEIX10OcXMX71EQBefLQ6Nf3dVU4kLJGjnY4p3RoA8OOeBNX3azN5eVm6dCmjRo1i/Pjx7N+/n4iICNq3b09KSspNj9+xYwe9e/fmhRde4MCBA3Tp0oUuXbpw+LD6szMycgt5f03JPiCvtKlBqK+ryomEJXu3Y10quNhzPCmLb65NXRWirE3bcJyUrAJCfV1LT/0LcT+ahnrTu2nJfm1vr4yjoFi9rQNMXl4++eQThgwZwqBBg6hbty5ffvklLi4ufPvttzc9/rPPPuPJJ5/kjTfeoE6dOkycOJGGDRsya9YsU0e9oynrj3Mlp5CaFd3476OyD4h4MN6uDrx9bRrijD/MaxqisA4x56+yaPcFACZ1qY+TvSznIB7MmCfr4O/hyMM1fTGqeMLYpOWlsLCQmJgY2rZt+78n1Gpp27YtO3fuvOljdu7cecPxAO3bt7/l8QUFBej1+htuprD7zBWW7ksAKBl5LfuAiDLQo1EQzav5kF9k5J1fzGcaorB8RQYjb19bzqF7wyBa1PBVO5KwAp4u9mwa3ZrxneqpuraZSd+B09LSMBgM+PvfuBCSv78/SUk3X+MiKSnpno6fMmUKnp6epbfg4OCyCf8P1fzceCYikN5NQ2hS1dskzyFsj0ajYVLX+jjYadl2MpXVBxPVjiSsxLy/znAiuWQ5h3c61lE7jrAi5rAqs8WfPoiOjiYzM7P0lpCQYJLn8XN35PPeUXzQpb5Jvr+wXdX83Bh+bSzCxLXmMQ1RWLbzV3L47I9TQMnYKlnOQVgbk5YXX19fdDodycnJN9yfnJxMQEDATR8TEBBwT8c7Ojri4eFxw82UZMdoYQr/fbQaNSq6kZZdaBbTEIXlUhSFd385TEGxkZY1fOgmyzkIK2TS8uLg4ECjRo3YtGlT6X1Go5FNmzbRvHnzmz6mefPmNxwPsHHjxlseL4Q1cLT739ov5jANUViuVbH/W87hgy6ynIOwTia/bDRq1CjmzZvHggULOHbsGC+99BI5OTkMGjQIgP79+xMdHV16/IgRI9iwYQPTp0/n+PHjvPfee+zbt4/hw4ebOqoQqmoa6k2vJiVjtqJXHFJ1GqKwTBm5hUxcW7Kcw6uPyXIOwnqZvLz07NmTjz/+mHHjxhEZGUlsbCwbNmwoHZR74cIFLl/+314JLVq0YPHixcydO5eIiAh+/vlnfvnlF+rXl7EmwvpFd6iDr5sjp1NzmLP1tNpxhIWZvP5Y6XIOQx+R5RyE9dIoVjY3U6/X4+npSWZmpsnHvwhhCmsOJvLKjwdw0GlZP+JhalR0UzuSsAA7T1+h97xdACx7sbnMihQW517evy1+tpEQ1ubpBpVoU9uPwmvrdBiNVvX5QphAfpGBt1fGAdC3mSznIKyflBchzIxGo2Fil/o42+vYcy6dn/aZZvq/sB6zt8RzNi2Hiu6OvPlkmNpxhDA5KS9CmKGgCi6MblcLKBnHkJKVr3IiYa5OJGWVjo+a8Ew9PJ3tVU4khOlJeRHCTA1sUZX6lT3Q5xeXbggqxP9nNCqMWXGIYqPCE3X9ebL+zdfDEsLaSHkRwkzZ6bR82K0BWg2sPXSZTceS7/wgYVMW7j7PgQsZuDroeL9zPVnTRdgMKS9CmLH6lT0Z/HA1AN795TDZBcUqJxLm4nJmHtM2nADgzSfDqOTprHIiIcqPlBchzNxrbWsR4u3C5cx8PtpwXO04wgwoisLYX46QXVBMZLAX/R6qonYkIcqVlBchzJyzw/+2Dvh+13lizsvWAbZuXdxl/jiWjL1Ow4fdw2XPNWFzpLwIYQFa1fTl2UZBKAq8tTxOtg6wYVdzCnlv9REAXmpdg7AAWYxT2B4pL0JYiHc61sHXzYH4lGy+2CJbB9iqD9YdIy27kBoV3RjWRrYAELZJyosQFsLLxYH3nqkHwBdb4zmZnKVyIlHe/jyZyvL9F9FoYGr3Bjja6dSOJIQqpLwIYUE6hleibR1/igwKb/58CINsHWAzcgqKeXtFyRYAA5pXpVGVCionEkI9Ul6EsCAlWwfUw93RjtiEDL7bflbtSKKcfPz7CS5l5FHZy5k32tdWO44QqpLyIoSFqeTpzNsd6wAlb2jn0nJUTiRMLeb8VebvOAfAlG7huDraqRtICJVJeRHCAvVqEkzLGj7kFxl5c/kh2XnaiuUXGXjj54MoCnRrWJlHavmpHUkI1Ul5EcICaTQaPuzWABcHHXvOpvPDrvNqRxIm8unGk5xJLdkxevzT9dSOI4RZkPIihIUK9nZhTIcwAKZuOE5Ceq7KiURZ23/hKvP+OgPA5K7heLrIjtFCgJQXISxav2ZVaBrqTW6hgTErDqEocvnIWuQXGXhj2UGMCnSNqkzbuv5qRxLCbEh5EcKCabUapnVvgJO9lu3xV/hxT4LakUQZ+fSPk5xOzcHP3ZHxneqqHUcIsyLlRQgLV9XXldfblUydnbTuqFw+sgIHLlxl3rb/XS7ycnFQOZEQ5kXKixBWYFDLUJpW9San0MDryw7K7CMLVjK76BBGBbpEBvKEXC4S4l+kvAhhBXRaDR8/G4GLg47dZ9P5Vhavs1gf/XaC+JRsfN0cGd9JZhcJcTNSXoSwEiE+LrzbsWRsxLTfTnBK9j6yODtOp/HN3yXFc2r3cCq4yuUiIW5GyosQVqR302Ba1/ajsNjIqJ8OUmQwqh1J3CV9fhGv/3QQKPn/8fE6crlIiFuR8iKEFdFoNEzt3gBPZ3viLmUye0u82pHEXXpv9RESM/MJ8f7fGTQhxM1JeRHCyvh7ODGxS30AZm6O59DFDHUDiTv6Ne4yK/ZfQquBT3tGyN5FQtyBlBchrNAzEYE83aASBqPCyCWx5BYWqx1J3EKKPp+3V8YB8OKj1WlUxVvlREKYP5OWl/T0dPr27YuHhwdeXl688MILZGdn3/YxrVu3RqPR3HB78cUXTRlTCKv0QZf6BHg4cSYth/fXHFU7jrgJRVF4a/khruYWUbeSByPb1lI7khAWwaTlpW/fvhw5coSNGzeydu1atm3bxtChQ+/4uCFDhnD58uXS27Rp00wZUwir5OXiwKc9I9FoYMneBNbHXVY7kviH77afY8uJVBzstMzoFYmDnZwMF+JumOw35dixY2zYsIGvv/6aZs2a0apVK2bOnMmSJUtITEy87WNdXFwICAgovXl4eJgqphBWrXl1H15uXR2AMcsPkZiRp3Iicd3hS5l8+OtxAN7tWIda/u4qJxLCcpisvOzcuRMvLy8aN25cel/btm3RarXs3r37to9dtGgRvr6+1K9fn+joaHJzb73ceUFBAXq9/oabEOJ/RratRUSwF/r8YkYujcUgq++qLqegmFd/PEChwUi7uv7856EqakcSwqKYrLwkJSVRsWLFG+6zs7PD29ubpKSkWz6uT58+LFy4kC1bthAdHc0PP/xAv379bnn8lClT8PT0LL0FBweX2c8ghDWw12n5vFckbo527DmbzhcyfVp141cf4UxaDpU8nZjWowEajUbtSEJYlHsuL2PGjPnXgNp/3o4fP37fgYYOHUr79u0JDw+nb9++fP/996xcuZLTp0/f9Pjo6GgyMzNLbwkJsquuEP9UxceViV1KlpqfsekUMefTVU5ku1bFXuLnmItoNTCjZ6RsuijEfbjnxQRGjx7NwIEDb3tMtWrVCAgIICUl5Yb7i4uLSU9PJyAg4K6fr1mzZgDEx8dTvXr1f/27o6Mjjo6Od/39hLBVXaOC+PNEKr/EJjJ88QHWvtIKHzf53SlP56/k8M7KwwC88lhNmlXzUTmREJbpnsuLn58ffn5+dzyuefPmZGRkEBMTQ6NGjQDYvHkzRqOxtJDcjdjYWAAqVap0r1GFEP/wQddw4i5lcjo1h5FLY5k/qCk6rVyyKA/5RQaGLd5PdkExTat688pjNdSOJITFMtmYlzp16vDkk08yZMgQ9uzZw/bt2xk+fDi9evUiMDAQgEuXLhEWFsaePXsAOH36NBMnTiQmJoZz586xevVq+vfvzyOPPEKDBg1MFVUIm+HmaMecfo1wttfx16k0Zm4+pXYkmzF+1REOX9JTwcWeGb0isdPJtGgh7pdJf3sWLVpEWFgYjz/+OE899RStWrVi7ty5pf9eVFTEiRMnSmcTOTg48Mcff9CuXTvCwsIYPXo03bt3Z82aNaaMKYRNqeXvzpRu4QB8tukU206mqpzI+i3Zc4Gl+xLQamBm74YEejmrHUkIi6ZRFMWq5k3q9Xo8PT3JzMyU9WGEuI23V8axePcFKrjYs+7Vh+UN1UTiLmbS/csdFBYbeaN9bYa1kctFQtzMvbx/y3lLIWzUuKfrUr+yB1dzixi2eD+FxUa1I1mdqzmFvLgwhsJiI23r+PPSo/+edCCEuHdSXoSwUU72Oub0bYSHkx0HLmQw9pfDWNmJWFUZjAojlsZyKSOPKj4uTH8uAq0MjhaiTEh5EcKGBXu78HnvKLQaWLovge+2n1M7ktWY/vsJtp1Mxcley5f9GuHpbK92JCGshpQXIWxc69oVefupOgB8sO4of8oA3gf2c8xFvthasrDmh90aUKeSjL8ToixJeRFC8EKrUJ5rHIRRgeGL9xOfkq12JIu1+8wVolccAmB4mxp0iaqsciIhrI+UFyEEGo2GiV3q06RqBbLyixny/T4yc4vUjmVxzqXl8N+FMRQZFDqGV2LUE7XUjiSEVZLyIoQAwNFOx5x+jajs5czZtBxeXhwjM5DuQWZuEc8v2EtGbhERQZ58/KwM0BXCVKS8CCFK+bo58vWAxrg46Ngef4XXlx3EaJQZSHdSZDDy8uIYzqTmEOjpxLwBjXF20KkdSwirJeVFCHGDOpU8+LJfI+y0GlYfTOT9tUdlCvVtGI0Kry87yPb4K7g66PhmYBMqujupHUsIqyblRQjxL4/U8mP6cxEAzN9xrnTmjLiRoiiMW32YVbGJ2Gk1zOrbUGYWCVEOpLwIIW6qc2Rlxj5dF4CPfjvBkj0XVE5kfj7+/QQLd11Ao4FPe0bSpnZFtSMJYROkvAghbumFVqG81LpkSfu3V8ax4XCSyonMx1d/nmb2lpIzUpO7htMpIlDlRELYDikvQojberN97dI1YF75cb8UGODHPReY8utxAMZ0CKN30xCVEwlhW6S8CCFuS6PRMLlrOE83qESRQWH44v2sO3RZ7ViqWbz7Am+vjAPgpdbVeVE2WxSi3NmpHUAIYf7sdFpm9IzETqvhl9hEXl1ygGKjkc6RtrV67LxtZ5i0/hgAA5pX4c32tVVOJIRtkvIihLgrdjot05+LxE6n5eeYi7y2NBaDUaFbwyC1o5mcoih8+scpPt90Cig54/Jm+9poNLIInRBqkPIihLhrOq2Gad0bYK/T8OOeBEYvO0hOQTH/aV5V7WgmoygKH6w7xjd/nwXgjfa1GdamhsqphLBtMuZFCHFPtFoNk7qE85+HqqAoMHbVEd5fcxSDFa7EW1hs5M2fD5UWl/c61ZXiIoQZkPIihLhnWq2G9zvX4/V2JRsPfrv9LEO/30d2QbHKycpOWnYBfb/exbKYi2g1MK1HAwa2DFU7lhACKS9CiPuk0WgY/lhNZvWJwtFOy6bjKfSYs4PEjDy1oz2ww5cyeWbm3+w9dxV3Jzu+GdCE5xoHqx1LCHGNlBchxAN5ukEgS4Y+hK+bI8eTsug8ezu7zlxRO9Z9W30wkR5f7iAxM59qvq78MqwlbcJk5VwhzImUFyHEA4sKqcAvw1pQ29+d1KwCes/bxbQNxyksNqod7a7lFxl4f81RXv3xAPlFRlrX9mPlsJZU93NTO5oQ4h+kvAghykRQBRdWvNyC5xoHoSjwxdbTdJ+zg9Op2WpHu6P9F67y1Gd/8e32koG5/320Gt8MaIKns73KyYQQN6NRrGyve71ej6enJ5mZmXh4yO6uQqhhfdxlolfEkZlXhLO9jnefrkPvJiFotea1Lkp+kYEZf5xi7rbTGBXw93Dkw24N5DKRECq4l/dvKS9CCJO4nJnH6J8OsuN0yfiXBkGevNuxLk1DvVVOVmLH6TTeW32Ek8klZ4a6RlXmvU718HSRsy1CqEHKi5QXIcyC0ajw7fazzPjjVOk06g71A4juUIcQHxdVMh1MyOCj307wd3waAL5uDkzqGk77egGq5BFClJDyIuVFCLOSmlXAp3+cZMmeCxgVcNBp6dMshP7Nq1CtnAbExqdkMf33k/x6bVdse52GPk1DGNG2Ft6uDuWSQQhxa2ZRXiZNmsS6deuIjY3FwcGBjIyMOz5GURTGjx/PvHnzyMjIoGXLlsyZM4eaNWve9fNKeRHCfB1P0jNp3TH+OpVWel+rGr70e6gKbetUxE5XtnMIcguL+TUuiZ9jLrLz2vRtjabkEtFrbWsR7K3O2R8hxL+ZRXkZP348Xl5eXLx4kW+++eauysvUqVOZMmUKCxYsIDQ0lLFjxxIXF8fRo0dxcnK6q+eV8iKEeVMUhb/j05i//RybT6Rw/S9QgIcTHRtUokV1H5qGeuPudH9jT/T5RcReyGDNwUTWx10mp9AAlJSWJ+r483r72tTydy+rH0cIUUbMorxcN3/+fEaOHHnH8qIoCoGBgYwePZrXX38dgMzMTPz9/Zk/fz69evW6q+eT8iKE5UhIz2Xxngv8tDeBKzmFpffrtBrqV/bkoWrehPq4UtHDkYruTlT0cMTL2YGcgmL0+UVk5Zf874UruRy4kMGBhKucSsnm//9Vq+LjQo+GQXRtWJmgCnKmRQhzdS/v32azq/TZs2dJSkqibdu2pfd5enrSrFkzdu7cecvyUlBQQEFBQenXer3e5FmFEGUj2NuFt54MY2Tbmmw6lsJfp9LYeTqNc1dyOZiQwcGEjPv6vkEVnGlZ3ZcejYNoXKUCGo15TdEWQjwYsykvSUklg+j8/f1vuN/f37/0325mypQpTJgwwaTZhBCm5Win46nwSjwVXgmASxl57Dx9hZjzV0nKzCMlq4CUrALSsgtKz6o42+vwcLbD3cmeiu6ORAZ7ERVSgchgL/zcHVX8aYQQpnZP5WXMmDFMnTr1tsccO3aMsLCwBwp1L6Kjoxk1alTp13q9nuBg2UBNCEtW2cuZHo2C6NEo6Ib7iw1GcgoMuDjqsC/jwb1CCMtxT+Vl9OjRDBw48LbHVKtW7b6CBASUrLGQnJxMpUqVSu9PTk4mMjLylo9zdHTE0VE+ZQlhC+x0WjxdpLQIYevuqbz4+fnh5+dnkiChoaEEBASwadOm0rKi1+vZvXs3L730kkmeUwghhBCWx2QfYS5cuEBsbCwXLlzAYDAQGxtLbGws2dn/26QtLCyMlStXAqDRaBg5ciQffPABq1evJi4ujv79+xMYGEiXLl1MFVMIIYQQFsZkA3bHjRvHggULSr+OiooCYMuWLbRu3RqAEydOkJmZWXrMm2++SU5ODkOHDiUjI4NWrVqxYcOGu17jRQghhBDWT7YHEEIIIYTqLHKdl7JyvYvJei9CCCGE5bj+vn0351SsrrxkZWUByHRpIYQQwgJlZWXh6el522Os7rKR0WgkMTERd3f3Ml9V8/oaMgkJCXJJSgXy+qtLXn91yeuvLnn9TU9RFLKysggMDESrvf18Iqs786LVagkKCrrzgQ/Aw8ND/uNVkbz+6pLXX13y+qtLXn/TutMZl+tktSchhBBCWBQpL0IIIYSwKFJe7oGjoyPjx4+X7QhUIq+/uuT1V5e8/uqS19+8WN2AXSGEEEJYNznzIoQQQgiLIuVFCCGEEBZFyosQQgghLIqUFyGEEEJYFCkvd2n27NlUrVoVJycnmjVrxp49e9SOZBOmTJlCkyZNcHd3p2LFinTp0oUTJ06oHctmffjhh2g0GkaOHKl2FJtx6dIl+vXrh4+PD87OzoSHh7Nv3z61Y9kEg8HA2LFjCQ0NxdnZmerVqzNx4sS72ntHmJaUl7uwdOlSRo0axfjx49m/fz8RERG0b9+elJQUtaNZvT///JNhw4axa9cuNm7cSFFREe3atSMnJ0ftaDZn7969fPXVVzRo0EDtKDfQaDS89957ascwiatXr9KyZUvs7e359ddfOXr0KNOnT6dChQpqR7MJU6dOZc6cOcyaNYtjx44xdepUpk2bxsyZM9WOJhRxR02bNlWGDRtW+rXBYFACAwOVKVOmqJjKNqWkpCiA8ueff6odxaZkZWUpNWvWVDZu3Kg8+uijyogRI255bHx8vDJ06FAlNDRUcXR0VNzd3ZUWLVooM2bMUHJzc8s8G6CMHz++zL+vOXjrrbeUVq1aqR3DZnXs2FF5/vnnb7ivW7duSt++fVVKJK6TMy93UFhYSExMDG3bti29T6vV0rZtW3bu3KliMtuUmZkJgLe3t8pJbMuwYcPo2LHjDb8HN7Nu3TrCw8P56aef6NSpEzNnzmTKlCmEhITwxhtvMGLEiDLPlpeXx7vvvlvm39ccrF69msaNG/Pss89SsWJFoqKimDdvntqxbEaLFi3YtGkTJ0+eBODgwYP8/fffdOjQQeVkwuo2ZixraWlpGAwG/P39b7jf39+f48ePq5TKNhmNRkaOHEnLli2pX7++2nFsxpIlS9i/fz979+697XFnz56lV69eVKlShc2bN1OpUqXSfxs2bBjx8fGsW7euzPM5OTmV+fc0F2fOnGHOnDmMGjWKt99+m7179/Lqq6/i4ODAgAED1I5n9caMGYNerycsLAydTofBYGDSpEn07dtX7Wg2T868CIsxbNgwDh8+zJIlS9SOYjMSEhIYMWIEixYtumNJmDZtGtnZ2XzzzTc3FJfratSoUXrmpbi4mIkTJ1K9enUcHR2pWrUqb7/9NgUFBTc8Zt++fbRv3x5fX1+cnZ0JDQ3l+eefv+GYf455ee+999BoNMTHxzNw4EC8vLzw9PRk0KBB5Obm/ivXwoULadSoEc7Oznh7e9OrVy8SEhLu9iUyKaPRSMOGDZk8eTJRUVEMHTqUIUOG8OWXX6odzSb89NNPLFq0iMWLF7N//34WLFjAxx9/zIIFC9SOZvPkzMsd+Pr6otPpSE5OvuH+5ORkAgICVEple4YPH87atWvZtm0bQUFBasexGTExMaSkpNCwYcPS+wwGA9u2bWPWrFkUFBSg0+kAWLNmDdWqVaNFixZ3/L6DBw9mwYIF9OjRg9GjR7N7926mTJnCsWPHWLlyJQApKSm0a9cOPz8/xowZg5eXF+fOnWPFihV3lf25554jNDSUKVOmsH//fr7++msqVqzI1KlTS4+ZNGkSY8eO5bnnnmPw4MGkpqYyc+ZMHnnkEQ4cOICXl9c9vFplr1KlStStW/eG++rUqcPy5ctVSmRb3njjDcaMGUOvXr0ACA8P5/z580yZMkXOfKlN7UE3lqBp06bK8OHDS782GAxK5cqVZcBuOTAajcqwYcOUwMBA5eTJk2rHsTl6vV6Ji4u74da4cWOlX79+SlxcXOlxmZmZCqB07tz5jt8zNjZWAZTBgwffcP/rr7+uAMrmzZsVRVGUlStXKoCyd+/e234//jFgd/z48Qrwr4GWXbt2VXx8fEq/PnfunKLT6ZRJkybdcFxcXJxiZ2f3r/vV0Lt3738N2B05cqTSvHlzlRLZFm9vb+WLL7644b7JkycrNWvWVCmRuE4uG92FUaNGMW/ePBYsWMCxY8d46aWXyMnJYdCgQWpHs3rDhg1j4cKFLF68GHd3d5KSkkhKSiIvL0/taDbB3d2d+vXr33BzdXXFx8fnhnFHer2+9Pg7Wb9+PVDye/X/jR49GqB0XMz1sx5r166lqKjonrO/+OKLN3z98MMPc+XKldKsK1aswGg08txzz5GWllZ6CwgIoGbNmmzZsuWen7Osvfbaa+zatYvJkycTHx/P4sWLmTt3LsOGDVM7mk3o1KkTkyZNYt26dZw7d46VK1fyySef0LVrV7Wj2Ty5bHQXevbsSWpqKuPGjSMpKYnIyEg2bNjwr0G8ouzNmTMHgNatW99w/3fffcfAgQPLP5C4KQ8PDwCysrLueOz58+fRarXUqFHjhvsDAgLw8vLi/PnzADz66KN0796dCRMm8Omnn9K6dWu6dOlCnz59cHR0vOPzhISE3PD19bVRrl69ioeHB6dOnUJRFGrWrHnTx9vb29/xOUytSZMmrFy5kujoaN5//31CQ0OZMWOGDBgtJzNnzmTs2LG8/PLLpKSkEBgYyH//+1/GjRundjSbJ+XlLg0fPpzhw4erHcPmKLKSpdnZunXrv+7z8PAgMDCQw4cP3/X30Wg0d/z3n3/+mV27drFmzRp+++03nn/+eaZPn86uXbtwc3O77eOvj8X5p+v/TRmNRjQaDb/++utNj73T9y8vTz/9NE8//bTaMWySu7s7M2bMYMaMGWpHEf8g5UUIUSaefvpp5s6dy86dO2nevPktj6tSpQpGo5FTp05Rp06d0vuTk5PJyMigSpUqNxz/0EMP8dBDDzFp0iQWL15M3759WbJkCYMHD36gvNWrV0dRFEJDQ6lVq9YDfS8hRPmSMS9CiDLx5ptv4urqyuDBg/81Ow/g9OnTfPbZZzz11FMA//o0+8knnwDQsWNHoOTyzj/PvEVGRgL8a0r1/ejWrRs6nY4JEyb863kUReHKlSsP/BxCCNOQMy9CiDJRvXp1Fi9eTM+ePalTpw79+/enfv36FBYWsmPHDpYtW8bAgQMZMWIEAwYMYO7cuWRkZPDoo4+yZ88eFixYQJcuXWjTpg0ACxYs4IsvvqBr165Ur16drKws5s2bh4eHR2kBetC8H3zwAdHR0Zw7d44uXbrg7u7O2bNnWblyJUOHDuX1119/4OcRQpQ9KS9CiDLzzDPPcOjQIT766CNWrVrFnDlzcHR0pEGDBkyfPp0hQ4YA8PXXX1OtWjXmz5/PypUrCQgIIDo6mvHjx5d+r+ulZsmSJSQnJ+Pp6UnTpk1ZtGgRoaGhZZJ3zJgx1KpVi08//ZQJEyYAEBwcTLt27XjmmWfK5DmEEGVPo8iISCGEEEJYEBnzIoQQQgiLIuVFCCGEEBZFyosQQgghLIqUFyGEEEJYFCkvQgghhLAoVjdV2mg0kpiYiLu7+x2XHxdCCCGEeVAUhaysLAIDA9Fqb39uxerKS2JiIsHBwWrHEEIIIcR9SEhIICgo6LbHWF15cXd3B0p++Os73QohhBDCvOn1eoKDg0vfx2/H6srL9UtFHh4eUl6EEEIIC3M3Qz5kwK4QQgghLIpJy8u2bdvo1KkTgYGBaDQafvnllzs+ZuvWrTRs2BBHR0dq1KjB/PnzTRlRCCGEEBbGpOUlJyeHiIgIZs+efVfHnz17lo4dO9KmTRtiY2MZOXIkgwcP5rfffjNlTCGEEEJYEJOOeenQoQMdOnS46+O//PJLQkNDmT59OgB16tTh77//5tNPP6V9+/aminlXig1GzqblUMHVgQouDui0Mg1bCGG+FEUhv8hIdkExOq2GCi72snyEsBpmNWB3586dtG3b9ob72rdvz8iRI2/5mIKCAgoKCkq/1uv1JsmWpM/niU+3AaDRgKezPd4uDni7OhBWyZ0mVb1pGupNJU9nkzy/EELcTGpWAYcuZnAwIYPYi5mcTskmK7+InEIDBqNSepyDTktFD0cCPJzw93Sitr87LWv4EhHkiZ1Ohj8Ky2JW5SUpKQl/f/8b7vP390ev15OXl4ez87+LwZQpU5gwYYLJs+UUGPBysScjtwhFgYzcIjJyiziTlsO+81dZuOsCAEEVnGla1ZtOkYE8UtNPztAIIcrc0UQ9K/ZfZMORJC5ezbvtsRoNKAoUGoxcvJpXevw6LvPJxpO4O9rRrJoPLWv40KF+JQI8ncrjRxDigZhVebkf0dHRjBo1qvTr6/PEy1rtAHdix7Wj2GAkI6+IqzmFXMkpJCWrgNgLGew9l86RxMxrfxwuseLAJSp7OfNs4yCebRxMZS85IyOEuH8p+nxWxSayfP9Fjidlld6v0UANPzcigr2ICPaibiV3PJ0dcHO0w83JDhd7HcVGhZSsfJL1+SRlFnA5M4/9F66yPf4KmXlF/HEsmT+OJfPBumO0q+tP/+ZVeaiat1xmEmbLrMpLQEAAycnJN9yXnJyMh4fHTc+6ADg6OuLo6Fge8QCw02nxdXPE182RmtfueyYiEIDsgmL2n7/K5uMprDxwiUsZecz44xSfbTpF61p+vPZELRoEeZVbViGE5bucmcfMzfH8tDeB4muXgRx0WtrWrUiXyMo0r+6Du5P9bb+Hg1ZDUAUXgiq43HC/wahwNFHP3/FpbD6ezN5zV/n1cBK/Hk6ilr8b/3moCs82DsbJXmeyn0+I+6FRFEW582Fl8EQaDStXrqRLly63POatt95i/fr1xMXFld7Xp08f0tPT2bBhw109j16vx9PTk8zMTFUXqcsvMvDbkSSW7Elg55krpfd3igjkjXa1CfFxuc2jhRC27kp2AV9sPc0Pu85TWGwEoGGIF90bBfF0eCCeLrcvLPfjeJKeH3aeZ+WBS+QWGgCo7OXMmA5hPN2gkpyJESZ1L+/fJi0v2dnZxMfHAxAVFcUnn3xCmzZt8Pb2JiQkhOjoaC5dusT3338PlEyVrl+/PsOGDeP5559n8+bNvPrqq6xbt+6uZxuZS3n5/86m5TBz8ylWHriEooC9TkO/h6rwymM18XZ1UDueEMKM5BcZmLP1NPP+OlNaIJpW9eb19rVpGupdLhn0+UUsj7nI3G1nuJyZD0DjKhUY16munD0WJmM25WXr1q20adPmX/cPGDCA+fPnM3DgQM6dO8fWrVtveMxrr73G0aNHCQoKYuzYsQwcOPCun9Mcy8t1RxIz+fDX4/x1Kg0ombE0sUv90stOQgjbdjAhg9eXHeRUSjYA4ZU9eb19bR6p6avKWY+8QgNzt53hyz9Pk1dUUqS6Nwxi7NN18HKRD16ibJlNeVGDOZeX6/46lcqkdcdKB911igjkg871TXIaWAhh/gqKDcz44xRf/XkaowK+bo6890xdOoabx6Way5l5fLThBCsOXAIgwMOJT3pG0KK6r8rJhDWR8mLm5QWgyGBk5uZ4Zm+Jx2BUCPBw4qNnG/BwTT+1owkhylHcxUxGL4vlZHLJ2ZbOkYG816keFczwkvL+C1d5/aeDnEnLQaOBFx+tzmtta+FgJ+vEiAcn5cUCyst1sQkZjFoay5m0HACebxnK20+FyaJRQtiAn/Ym8O4vhyk0GPF1c2BS13Da1wtQO9Zt5RYW8/6aoyzZmwBAgyBPPusVRaivq8rJhKWT8mJB5QVKritP+fUY3+88D0CrGr7M7tNQLiMJYaWKDEY+WHuUBdd+59vV9Wdq9wZmebblVn6Nu8yYFXFk5hXh6qBjVp+GtAmrqHYsYcGkvFhYebluw+EkXlsaS16RgWq+rnw9oDHV/NzUjiWEKENXsgsYtng/u86kAzDqiVoMb1MDrQWuxp2YkcfIJbHsOZeOVgPvPVOP/s2rqh1LWKh7ef+WaxNm5Mn6Afz8UnMCPZ04k5ZDl9nb+fvazCQhhOU7mqjnmVnb2XUmHVcHHXP/04hXH69pkcUFINDLmYWDm9GjURBGBcatOsKENUdu2FNJCFOQ8mJm6gV6smp4KxqGeKHPL2bAd3v4cc8FtWMJIR7QvnPp9Jy7k0sZeVT1ceGXYS1pZ+bjW+6Gg52Wj3o04I32tQH4bvs5hn6/j5yCYpWTCWsm5cUM+bk7snjIQ3SLqozBqBC9Io5v/j6rdiwhxH3adjKV/3yzh6z8YppW9WbVsFbU9HdXO1aZ0Wg0DGtTg1l9onCw07LpeAq95u4iI7dQ7WjCSkl5MVNO9jqmPxfBi49WB2Di2qPM3hKvciohxL3acPgygxfsI6/IwKO1/FjwfFOrHYz/dINAlgx9CG9XB+IuZdJn3m7Sc6TAiLIn5cWMaTQa3nqyNiPblmwB+dFvJ/jk9xNY2RhrIazW8piLvLxoP4UGI0+FBzCvf2OcHax7k8OGIRVYOvQhfN0cOXpZT595u7iSXaB2LGFlpLyYOY1Gw8i2tRjTIQyAzzfHM+XX41JghDBzS/ZcYPSygxgVeLZREJ/3irKZxdxq+ruzZOhDVHR35HhSFr3n7SI1SwqMKDu28ZtkBV58tDoTnqkHwNxtZ5jy63GVEwkhbmXNwUSiV8YBMLBFVaZ2b2BzC0/WqOjGkqEP4e/hyMnkbHrN3UmKPl/tWMJK2NZvk4Ub0KIqU7qFA5RuliaEMC+bjyfz2tJYFAX6NgthfKe6FjsV+kFV83Nj6dCS5R9Op+bQ75vdZOYWqR1LWAEpLxamd9MQ3nmqDgAf/nqcJTKNWgizsevMFV5auJ9io0LnyEAmdq5vFhsrqqmqrytLhjYvPQPzwoK95F/boVqI+yXlxQINeaQaL7UumYX09so4Nhy+rHIiIcShixkMXrCPgmIjj4dV5ONnI2z2jMs/hfi4sOD5prg72bHv/FWGLz5AscGodixhwaS8WKg329emV5NgjAq8+mMsO+JlJV4h1HI6NZsB3+4hu6CY5tV8mN23IfY2NsblTsICPPhmQBMc7LT8cSyZd1YelokH4r7Jb5eF0mg0TOoazpP1Aig0GBny/T6OJGaqHUsIm5OeU8jz8/dyNbeIiCBP5g1ojJO9dU+Hvl9NQ72Z2TsKrQaW7ktg+u8n1Y4kLJSUFwum02r4rHckLar7kFNoYPCCfaRkyWh+IcpLQbGBF3+I4fyVXIIqOPPNwCa4OdqpHcusta8XwKSuJRMPZm2JZ9Hu8yonEpZIyouFc7TTMadfI6r5uXI5M5+h38fIYDghyoGiKEQvj2PPuXTcHe34dmATfN0c1Y5lEXo3DeG1trUAGL/qCDtPX1E5kbA0Ul6sgKezPd8OaIKnsz2xCRm8+fMhuZYshInN3hLPigOX0Gk1zO7bkFpWtFdReXj18Ro8ExFIsVHhpUUxXLiSq3YkYUGkvFiJqr6uzOnXEDuthtUHE5m1WfZBEsJU1h5K5ONr4zXee6Yej9TyUzmR5dFoNEzr0YCIIE8ycosY/P1esvJlDRhxd6S8WJEW1X2Z2KU+ANM3nmR9nEyhFqKsHb6UyeifDgLwfMtQ/vNQFZUTWS4nex1f/acxFd1L1oB5bWksBqOcNRZ3JuXFyvRuGsILrUIBGPVTLMcu61VOJIT1yMgt5KVFMRQUG2ld2493OtZRO5LFC/B0Ym7/xtemUKfw8e8n1I4kLICUFyv09lN1eKSWH/lFRl5aGINeTsUK8cCMRoURS2JJSM8jxNuFz3pGoZNF6MpEZLAXH/VoAMCcradZd0jOGovbk/JihXRaDZ/1jKSylzPnruTyxrKDMoBXiAf02aZT/HkyFUc7LXP6NcTTxV7tSFalc2Rl/vtoNQDeWn6IM6nZKicS5kzKi5Wq4OrAF30b4qDT8tuRZOb9dUbtSEJYrM3Hk/ls0ykAJncNp16gp8qJrNMb7WrTLNSb7IJiXl60n7xCWfZB3JyUFysWEezFuE51AZi64QS7zshaCkLcqwtXchm5JBaAfg+F0L1RkLqBrJidTsvM3lH4ujlyPCmLcasOqx1JmCkpL1aub7MQukVVxmBUGL74ACl6WYFXiLuVX2TgxYUx6POLiQrxYtzT9dSOZPUqejjxee9ItBpYFnORn/YmqB1JmKFyKS+zZ8+matWqODk50axZM/bs2XPLY+fPn49Go7nh5uTkVB4xrdL1PZBq+7uTll3A8B8PyFREIe7Sh78e5+hlPd7XL8Payee98tCiui+j29UGYOyqwxxNlFmT4kYm/01cunQpo0aNYvz48ezfv5+IiAjat29PSkrKLR/j4eHB5cuXS2/nz8veFw/C2UHHnH4NcXO0Y8/ZdFnAToi7sPFoMvN3nANg+rMRVPJ0VjeQjXnp0eq0qe1HQbGRlxfFkF1QrHYkYUZMXl4++eQThgwZwqBBg6hbty5ffvklLi4ufPvtt7d8jEajISAgoPTm7+9v6phWr5qfGxO7lJzy/mzTSfadS1c5kRDm63JmHm/8XLIQ3QutQmkTVlHlRLZHq9Xw6f+bNTl+1RG1IwkzYtLyUlhYSExMDG3btv3fE2q1tG3blp07d97ycdnZ2VSpUoXg4GA6d+7MkSO3/o+2oKAAvV5/w03cXNeoILpFVcaowIglsWTmyvovQvyTwagwckksGblFhFf25M0na6sdyWZ5uTgwo1fJ+Jfl+y+yKvaS2pGEmTBpeUlLS8NgMPzrzIm/vz9JSUk3fUzt2rX59ttvWbVqFQsXLsRoNNKiRQsuXrx40+OnTJmCp6dn6S04OLjMfw5r8n6X+lTxceFSRh5vr4yT9V+E+IdZm+PZfTYdVwcdM3tH4WinUzuSTWtS1Zvhj9UE4N2Vh0lIlw0chRnONmrevDn9+/cnMjKSRx99lBUrVuDn58dXX3110+Ojo6PJzMwsvSUkyMj023FztOPzXlHYaTWsi7vMT/vk9RLiuj1n0/lsU8mGi5O6hlPV11XlRALg1cdq0DDEi6yCYl5bGkuxwah2JKEyk5YXX19fdDodycnJN9yfnJxMQEDAXX0Pe3t7oqKiiI+/+SBTR0dHPDw8briJ24sI9uL19iWnwt9bfZT4FFnJUgh9fhGvLY3FqED3hkF0iaqsdiRxjZ1Oy2e9onB3tGPf+avM2iKTDmydScuLg4MDjRo1YtOmTaX3GY1GNm3aRPPmze/qexgMBuLi4qhUqZKpYtqkoQ9Xo1UNX/KKDIxceoDCYvkkI2zbe6uPcCmjZN+i9zvLei7mJtjbhQ+61gfg802nZNKBjTP5ZaNRo0Yxb948FixYwLFjx3jppZfIyclh0KBBAPTv35/o6OjS499//31+//13zpw5w/79++nXrx/nz59n8ODBpo5qU7RaDZ88F4GXiz2HL+mZtfmU2pGEUM2vcZdZsf8SWg182jMCV0c7tSOJm+gcWfmGSQdZsumszTJ5eenZsycff/wx48aNIzIyktjYWDZs2FA6iPfChQtcvvy/HUSvXr3KkCFDqFOnDk899RR6vZ4dO3ZQt25dU0e1ORU9nJjUJRyA2VtPc+DCVZUTCVH+UvT5vL0yDoCXWlenURVvlROJ25nQuR5BFZy5lJHHB2uPqR1HqESjWNl0E71ej6enJ5mZmTL+5S6NXHKAX2ITqebryrpXH8bZQWZXCNugKAqD5u9l64lU6gV6sPLllrKKrgXYdeYKveftQlHg24GNeSxM1gKzBvfy/i2/pYIJz9QnwMOJM2k5fPirfJIRtmPxngtsPZGKg52WT3tGSnGxEA9V8+H5lqEAvLU8jqs5hSonEuVNflMFni72fPRsAwAW7DzPX6dSVU4khOmdTcspvezw1pNh1PJ3VzmRuBdvtK9NjYpupGYV8K7sPm1zpLwIAB6u6ceA5lUAeGPZIVl9V1g1g1HhjWUHySsy0KK6D4NaVFU7krhHTvY6PnkuAp1Ww7pDl1l9MFHtSKIcSXkRpcZ0qEM1X1eS9PlMWCP7iAjrNX/HOfadv4qbox3TejRAq9WoHUnchwZBXgxrUwOAsb8cJkWfr3IiUV6kvIhSzg46Pn4uAq0GVhy4xObjyXd+kBAW5mxaDh/9dhyAt5+qQ1AFF5UTiQfxymM1qF/Zg8y8IsaskC1PbIWUF3GDhiEVeKFVyUC46BVxZObJ5SNhPa5fLsovMtKqhi+9m8peaJbOXqflk+cicdBp2Xw8hV9k80abIOVF/MvodrUJ9XUlWV/AB2uPqh1HiDKz4NrlIlcHHR92D0ejkctF1qCWvzsj2pZs3vje6qOkZMnlI2sn5UX8i5O9jmk9GqDRwLKYi2w9kaJ2JCEe2Nm0HKZdv1zUUS4XWZuhj1SjXmDJ5aOxvxyWy0dWTsqLuKkmVb0ZeG0GRvSKOPSyDLewYEajwps/l1wualnDhz5NQ9SOJMqYvU7LRz0isNNq+O1IMuviLt/5QcJiSXkRt/RG+9qEeLtwOTOfKetl8TphuX7YdZ69565dLurWQC4XWam6gR68fG320fhVR7iSXaByImEqUl7ELbk4lEwjBfhxTwJ/n0pTOZEQ9+7i1Vymbii5XDSmQxjB3nK5yJoNb1OD2v7uXMkp5L01MmbPWkl5Ebf1UDUf+l9bvC565SHyCg0qJxLi7imKwtsrD5NbaKBpVW/6NquidiRhYg52Wj56tgE6rYY1BxP57UiS2pGECUh5EXf05pNhBHo6kZCexycbT6gdR4i7tvLAJbadLNm7aEr3cFmMzkY0CPJi6CPVABi36rCM2bNCUl7EHbk52jGpazgA3/x9loMJGeoGEuIupGUX8P61qf4jHq9JdT83lROJ8jTi8ZqlSz58+OtxteOIMiblRdyVNmEV6RwZiFGBt5YfoshgVDuSELf13uojZOQWUbeSR+mncGE7nOx1TOlW8qFr8e4L7D5zReVEoixJeRF3bdzTdangYs/xpCy++vO02nGEuKWNR5NZe+gyOq2GaT0aYK+TP3W26KFqPqWrKEeviCO/SMbsWQv5jRZ3zcfNkXGd6gLw+aZ44lOyVU4kxL/p84t495c4AIY8XI36lT1VTiTUNKZDHSq6O3ImLYeZm0+pHUeUESkv4p50iaxM69p+FBqMRK84hNEoq1gK8zJtw3GS9QWE+roy8tqS8cJ2eTrb837n+gB89ecZjibqVU4kyoKUF3FPNBoNH3Spj6uDjr3nrvLj3gtqRxKi1L5z6SzcVfLf5OSu4TjZ61ROJMzBk/UDeLJeAMVGhTErDmGQD10WT8qLuGdBFVx4vX1tAD5cf5xkvWyCJtRXUGwgekXJ5aLnGgfRvLqPyomEOZnQuR7uTnYcupjJd9vPqh1HPCApL+K+9G9elYggT7IKipmw5ojacYTgqz/PcColG183B95+qo7acYSZ8fdwIrpDyX8Xn2w8yaWMPJUTiQch5UXcF51Ww5RuJatYro9LYuPRZLUjCRt2OjWbWZvjARjXqR5eLg4qJxLmqFeTYJpUrUBuoUF2nrZwUl7Efasb6MGQh/+3imV2QbHKiYQtMhoVolfEUWgw0rq2H50aVFI7kjBTWq2GKd3Csddp2Hw8hfVxsnWApZLyIh7IiMdrlu48/fFvsnWAKH8/7Utgz9l0nO11TOxcX3aMFrdVo6I7L7e+tvP06iNk5srWAZZIyot4IM4OOiZ1LZmGuGDnOWJl6wBRjlKy8pm8/hgAo9vVkh2jxV15uU11qvm5kpZdwIcbZOsASyTlRTywh2v60S2qMooCY2TrAFGOJq49hj6/mPqVPRjYoqracYSFcLTTMeXafm0/7rnAnrPpKicS90rKiygT73SsU7p1wDd/yzREYXpbT6Sw5mAiWg182K0BdrIFgLgHzW7YOuAQBcWydYAlKZff9tmzZ1O1alWcnJxo1qwZe/bsue3xy5YtIywsDCcnJ8LDw1m/fn15xBQPwMfNsXR66ow/TpKQnqtyImHNcguLefeXwwAMahkqWwCI+zLmyTr4ujlyOjWHL7eeUTuOuAcmLy9Lly5l1KhRjB8/nv379xMREUH79u1JSUm56fE7duygd+/evPDCCxw4cIAuXbrQpUsXDh8+bOqo4gH1aBRE82o+5BcZeUemIQoT+uyPU1y8mkdlL2dGPVFL7TjCQnm62Jfu1zZ7SzxnUmW/NkuhUUz8DtOsWTOaNGnCrFmzADAajQQHB/PKK68wZsyYfx3fs2dPcnJyWLt2bel9Dz30EJGRkXz55Zd3fD69Xo+npyeZmZl4eHiU3Q8i7sqZ1Gye/OwvCouNfNYrks6RldWOJKzMkcRMnpm1HYNR4ZsBjXm8jr/akYQFUxSFgd/t5c+TqTSv5sPiIc1kxppK7uX926RnXgoLC4mJiaFt27b/e0KtlrZt27Jz586bPmbnzp03HA/Qvn37Wx5fUFCAXq+/4SbUU83PjeFtSqYhTlx7VKYhijJlMCq8vSIOg1HhqfAAKS7igV3fr83JXsvOM1f4Oeai2pHEXTBpeUlLS8NgMODvf+MfGH9/f5KSbr44UFJS0j0dP2XKFDw9PUtvwcHBZRNe3LcXH61OjYpupGUX8uGGY2rHEVbkh53nOHgxE3dHO8Z3qqd2HGElgr1dGNm25PLjpPXHuJJdoHIicScWPzw/OjqazMzM0ltCQoLakWyeg52WKd2uT0NMkGmIokxczszjo2sLIb75ZG38PZxUTiSsyQutQgkLcCcjt4hJ6+RDl7kzaXnx9fVFp9ORnHzjvjfJyckEBATc9DEBAQH3dLyjoyMeHh433IT6mlT1Lp2G+PbKOJmGKB7Y+FVHyCk00DDEi77NqqgdR1gZe13Jhy6NBlYcuMTfp9LUjiRuw6TlxcHBgUaNGrFp06bS+4xGI5s2baJ58+Y3fUzz5s1vOB5g48aNtzxemK/r0xDjU7JlGqJ4IL8dSeL3o8nYXdsQVKuVAZWi7EWFVOA/D5UU43d+iSO/SD50mSuTXzYaNWoU8+bNY8GCBRw7doyXXnqJnJwcBg0aBED//v2Jjo4uPX7EiBFs2LCB6dOnc/z4cd577z327dvH8OHDTR1VlLF/TkM8LdMQxX3Iyi9i/KojAAx9pBq1A9xVTiSs2Rvta+Pv4cj5K7nM3HxK7TjiFkxeXnr27MnHH3/MuHHjiIyMJDY2lg0bNpQOyr1w4QKXL18uPb5FixYsXryYuXPnEhERwc8//8wvv/xC/fr1TR1VmECnBpV4tJYfhQYjb6+Ik7VfxD2b/vtJkvT5VPFx4dXHa6odR1g5dyd7JjxT8n7z1Z9nOJ4kM1jNkcnXeSlvss6L+UlIz6Xdp9vIKzIwrXsDnmsiM8LE3Tlw4Srd5uxAUWDhC81oVdNX7UjCRgz5fh8bjyYTFeLF8hdbyKXKcmA267wIASXTEF97ouQT86T1x0iTaYjiLhQZjESviENRoFtUZSkuoly937kerg46DlzIYNHu82rHEf8g5UWUi+dbhlK3kgeZeUVMXHtU7TjCAnzz91mOJ2VRwcWedzrWUTuOsDGVPJ1588kwAKZtOEFSZr7KicT/J+VFlAu7a9MQtRpYFZvInydT1Y4kzNj5Kzl8uvEkAG8/VQcfN0eVEwlb1O+hKkQGe5FVUMx7q4+oHUf8P1JeRLmJCPZiQIuqALyzMo7cwmJ1AwmzpCjKtbWBjLSs4UOPRkFqRxI2SqfVMKVbOHZaDRuOJPH7kZuv9C7Kn5QXUa5eb1ebyl7OXLyaxye/n1Q7jjBDy/dfYnv8FRzttEzqEi6b5AlV1ankwZBHqgEwbtURsvJlvzZzIOVFlCtXRzs+6FoyDfHb7Wc5mJChbiBhVtKyC/hgXcmYqJFta1HV11XlRELAiMdrUsXHhSR9PtM2nFA7jkDKi1BBm9oVeSYiEKMCY1bEUWQwqh1JmImJa4+SkVtEnUoeDH44VO04QgDgZK8r3a/th13n2XdO9mtTm5QXoYpxneri5WLPsct6vv7rrNpxhBnYciKFVbGJaDUwtXs49jr58yTMR4vqvvRsXLJG1VvLD8l+bSqTvw5CFb5ujrzbsWTrgBl/nORcWo7KiYSacgqKeXflYQAGtQylQZCXuoGEuIm3nyrZr+10ag6zt5xWO45Nk/IiVNO9YWVa1fCloPj6YmRWtdizuAcf/36CSxl5VPZyZtQTtdSOI8RNebrY837negDM2RrPiaQslRPZLikvQjUajYbJXcNxstey88wVlu5NUDuSUEHM+XTm7zgHwJRu4bg62qkbSIjb6FA/gCfq+lNkUHhr+SEMRvnQpQYpL0JVIT4ujH6iNgCT1h2TVSxtTH6RgTd/PoSiQI9GQTxSy0/tSELclkajYWLn+rg72hGbkMGCa8VblC8pL0J1z7cKJeLaKpbvrJTLR7Zk1uZ4Tqfm4OfuyNhrY6CEMHcBnk681aFk64CPfjvBhSu5KieyPVJehOp0Wg0f9WiAvU7DpuMprD6YqHYkUQ6OJGYy58+SQY8TO9fD08Ve5URC3L0+TUN4qJo3eUUG3lp+CKNcPipXUl6EWajl784rj5XsPP3e6iOy87SVKzIYefPnkvECT4UH8GT9SmpHEuKeaLUapnZvUDpm78e9F9SOZFOkvAiz8VLr6oQFuHM1t0g2QbNy8/46w5FEPZ7O9rz3TD214whxX6r4uPJG+5LLR1PWH+dSRp7KiWyHlBdhNux1Wj7qEYFOq2Htocv8JpugWaX4lCxm/HEKgHFP16Wiu5PKiYS4fwNbVKVRlQpkFxTztiz5UG6kvAizEh7kydBrm6C9+8thMnILVU4kylKxwcjoZYcoLDbSurYf3RpWVjuSEA9Ed+3ykYOdlj9PprJ8/yW1I9kEKS/C7Ix4vCbV/VxJzSpgvFw+sipz/zrDwYQM3J3s+LBbA9kxWliFGhXdeK1tyeKK7685QrJelnwwNSkvwuw42ev4+NkItBpYFZvIhsOX1Y4kysCJpCxmbCy5XDS+Uz0CPOVykbAeQx4OpUGQJ/r8YsYsPySXj0xMyoswS1EhFXjx0eoAvLPyMFdk9pFFKzIYeX3ZQQoNRh4Pq0h3uVwkrIydTsvHz0bgYKdly4lUWTHcxKS8CLM1om1NwgLcuZJTyLu/HJZPMhbsy62nibuUiaezPZO7hcvlImGVavm783q7kstHE9ceJSFdFq8zFSkvwmw52pVcPrLTavj1cJIsXmehjibq+XxzyeWiCc/Uw99DLhcJ6/VCq2o0qVqBnEIDb/x8UBavMxEpL8Ks1a/syfDHagAwbtURUmQgnEUpKDYwetlBigwK7er60zkyUO1IQpiUTqvh42cjcLbXsevM/zYdFWVLyoswe8Pa1KB+ZQ8y84oYI+soWJRPNp7k2GU9FVzs+aBrfblcJGxCFR9X3u5YB4CpG45zOjVb5UTWR8qLMHv2Oi2fPBeJg07L5uMpLNwty3Bbgl1nrjB32xkAPuzeQBajEzalX7MQHq7pS0GxkVE/HaTYYFQ7klWR8iIsQi1/99JdXCetO0p8inySMWeZeUWM/ukgigI9GwfTvl6A2pGEKFcaTcnide5OdhxMyODzzfFqR7IqUl6ExRjUoioP1/Qlv8jIyKUHKCyWTzLmavyqw1zKyKOKjwvjOtVVO44Qqgj0cuaDLvUBmLX5FHvPpaucyHqYtLykp6fTt29fPDw88PLy4oUXXiA7+/afmFu3bo1Go7nh9uKLL5oyprAQ2msD4Sq42HP4kp5PNp5UO5K4idUHE/klNhGdVsOnPSNxdbRTO5IQqukcWZluUZUxKjBySSyZeUVqR7IKJi0vffv25ciRI2zcuJG1a9eybds2hg4desfHDRkyhMuXL5fepk2bZsqYwoL4ezgxpVsDAL7adpqdp6+onEj8f4kZeby7Mg6A4W1q0DCkgsqJhFDfhM71CPF24VJGHmNlzaoyYbLycuzYMTZs2MDXX39Ns2bNaNWqFTNnzmTJkiUkJt5+vQ4XFxcCAgJKbx4eHrc8tqCgAL1ef8NNWLcn6wfQq0kwigKjfoolM1c+yZiDYoOR15bGos8vJjLYq3SKuxC2zt3Jnhm9ItFpNaw+mMjKA7J544MyWXnZuXMnXl5eNG7cuPS+tm3botVq2b17920fu2jRInx9falfvz7R0dHk5t56lcIpU6bg6elZegsODi6zn0GYr7FP16WqjwuXM/MZs0L2ETEHn2+OZ/fZdFwddHzaMxJ7nQypE+K6hiEVGPF4TaBkzaoLV2T13Qdhsr8uSUlJVKxY8Yb77Ozs8Pb2Jikp6ZaP69OnDwsXLmTLli1ER0fzww8/0K9fv1seHx0dTWZmZuktIUH2k7AFro52fNYrCntdyeq7P+w6r3Ykm7Y9Po2Z11bRndwtnFBfV5UTCWF+hrWpQZOqFcguKObVJTLp4EHcc3kZM2bMvwbU/vN2/Pjx+w40dOhQ2rdvT3h4OH379uX7779n5cqVnD59+qbHOzo64uHhccNN2IaIYC/GdChZCOqDtceIu5ipciLblJpVwIglsSgK9GoSTOdI2XRRiJu5Pojdw8mO2IQMPvz1/t8rbd09l5fRo0dz7Nix296qVatGQEAAKSkpNzy2uLiY9PR0AgLufs2HZs2aARAfL3Pkxb8937Iq7er6U2gwMmzxfvT5Mv6lPBmMCq8tjSUtu4Da/u6M71RP7UhCmLWgCi5Mfy4SgG+3n2XD4cvqBrJQ9zyH0c/PDz8/vzse17x5czIyMoiJiaFRo0YAbN68GaPRWFpI7kZsbCwAlSpVuteowgZoNBo+6hHB0Zl/cSE9lzHLDzG7T0NZhr6czNkaz9/xaTjb65jVJwpnB53akYQwe0/U9WfoI9WYu+0Mbyw7RJ1KHlTxkUut98JkY17q1KnDk08+yZAhQ9izZw/bt29n+PDh9OrVi8DAks3ZLl26RFhYGHv27AHg9OnTTJw4kZiYGM6dO8fq1avp378/jzzyCA0aNDBVVGHhPF3smdWnIfY6Devjkvh+p4x/KQ+7zlwpXWvn/c71qOnvrnIiISzHG+1r07hKBbIKinl50X7yiwxqR7IoJp0OsGjRIsLCwnj88cd56qmnaNWqFXPnzi3996KiIk6cOFE6m8jBwYE//viDdu3aERYWxujRo+nevTtr1qwxZUxhBSKDvYi+Nv5l0rpjHEzIUDeQlbucmcfwxfsxKtAtqjI9GgWpHUkIi2Kv0zKzTxTerg4cSdTz/tqjakeyKBrFyuaY6vV6PD09yczMlMG7NkZRFF5cGMNvR5Kp5OnE6uGt8HN3VDuW1ckvMtBz7i4OJmQQFuDOypdbyuUiIe7TtpOpDPhuD4oCn/aMoGuU7X4QuJf3b1mIQVgNjUbDR89GUM3PlcuZ+by8KEamIpYxRVEYt+owBxMy8HS2Z+5/GktxEeIBPFLLj1ceK1n/ZczyOA5dzFA3kIWQ8iKsioeTPfP6N8bd0Y69564yYc0RtSNZlUW7L/DTvotoNTCzdxQhPi5qRxLC4o14vCaPhVWkoNjI0O9jSNHnqx3J7El5EVanup8bn/eOQqMpebNdvPuC2pGsQsz59NIy+Eb7MB6pdedZh0KIO9NpNXzWK5IaFd1I0ufz34UxFBTLAN7bkfIirFKbsIq83q42AONXH2afbEX/QJIy83lx4X6KDApPhQfw4qPV1I4khFVxv3bW2MPJjgMXMnhnpWzgeDtSXoTVerl1dTqGV6LIoPDiwv1cyshTO5JFysovYtD8vaRmFVDL342PekTIOjpCmECoryuz+zZEq4GfYy7yzd9n1Y5ktqS8CKtVMoC3AWEB7qRlFzDw2z2yA/U9KjIYGbb4AMcu6/F1c+SbAU1wdbzntS2FEHfp4Zp+vNuxLgCT1x9jy4mUOzzCNkl5EVbNxcGObwc2IcDDiVMp2Qz5YZ9cS75LiqIw9pfDbDuZirO9jm8HNibYWwboCmFqg1pW5bnGQRgVeHnhfmJl3ap/kfIirF6glzPzn2+Cu6Mde86mM/qngxiNci35Tr7YepolexPQauDz3lE0CPJSO5IQNkGj0fBBl3AerulLXpGB5+fv5WxajtqxzIqUF2ETwgI8+Oo/jbDXaVh76DIfbpDdXG9nVewlPvrtBADjO9Xjibr+KicSwrY42GmZ068R4ZU9Sc8ppP+3u0nJkinU10l5ETajRQ1fPuoRAcDcbWf4brsMhruZLSdSeH3ZQQBeaBXKgBZV1Q0khI1ycyy57F3Fx4WE9DwGfbeXrHwZtwdSXoSN6RJVmTefLJlCPWHNUX7am6ByIvOyIz6NF3+Iocig0DG8Em8/VUftSELYND93R75/vim+biV7IL0oa8AAUl6EDXrp0eoMalkVgLdWHGJ5zEV1A5mJvefSeWHBPgqKjbStU5EZvSLRaWVKtBBqq+LjyrcDm+DioGN7/BVe/CHG5nehlvIibI5Go2Hc03X5z0NVUBR4/eeD/HLgktqxVBWbkMGg7/aSV2Tg4Zq+zOrTEHud/HkQwlw0CPLi6/6NcbLXsuVEKi8utO0CI3+dhE3SaDRMeKYefZqFoCgw6qdY1hxMVDuWKo4kZtL/m91kFxTzUDVv5v6nMU72stmiEOamRQ1fvh3YBCd7LVtPpPJfGz4DI+VF2CytVsMHnevTs3EwRgVGLo1l7SHbKjAx59PpM283+vxiGoZ48c2AJrJLtBBmrEV1X74b2BRnex1/nkxlyPf7bLLASHkRNk2r1TClWzg9GgVhMCq88uMBFuw4p3ascrHpWDJ9v95NZl4RDUO8mP98U1k9VwgL0Ly6D98NaoKzvY6/TqUxeME+sguK1Y5VrqS8CJun1WqY2r1B6SWk8auP8OGvx616Ibtl+xIY+kMM+UVG2tT2Y9Hgh/Bwslc7lhDiLj1UzYf5g0oG8f4dn8azX+4kKdN21oGR8iIEJVvST+pSn9fb1QLgyz9PM+qnWAqLjSonK1uKovDln6d54+dDGIwK3RpWZm7/xnKpSAgL1KyaDz8OeQhfN0eOXdbTZfZ2jibq1Y5VLqS8CHGNRqNh+GM1+ahHA+y0Gn6JTWTgd3vQW8miUIXFRsatKjmrBPDfR6ox/dkImVUkhAWLCPZi5cstqFHRjSR9Ps9+ucMmNnOUv1pC/MOzjYP5ZmATXB107Dh9hc6ztnMkMVPtWA8kMSOP577ayQ+7zgPw9lNhRD9VB41G1nERwtIFe7uw/KUWtKjuQ06hgcEL9rFgxzkUxXovfUt5EeImHq3lx9L/NifQ04mzaTl0/WIHi3aft8g/Bn+fSuPpmX8Tm5CBh5Md3w5szNBHqqsdSwhRhjyd7Zk/qCndG5ZMPhi/+ggvLdxPRm6h2tFMQqNY4l/j29Dr9Xh6epKZmYmHh4facYSFu5pTyOhlB9l8vOQ07DMRgUzuFo6bBczKMRoVvtgaz/SNJ1EUqBfowZf9GhHs7aJ2NCGEiSiKwjd/n2XqhuMUGRQCPZ2Y0SuKpqHeake7o3t5/5byIsQdGI0K8/46w7TfTmAwKlTzdeWjZyNoVKWC2tFu6WRyFtEr4og5fxWAXk2Cee+ZerL4nBA2Iu5iJq/8uJ9zV3LRamDE47UY/lgNs97yQ8qLlBdhAjHn0xm++ACXr01H7Nk4mLc6hOHt6qBysv/JLzLwxZZ45vx5miKDgquDjvGd6vFck2C1owkhyll2QTHjVx1h+f6S/dvqBXrw3jP1aFLVPM/CSHmR8iJM5GpOIVN+PcZP+0r+GHi52PNm+zB6NQlGq/Inmp2nr/DOyjjOpOUA0LZORd7vXJ9AL2dVcwkh1PXLgUuMXXWYrPySheyeiQgk+qkwKnma198GKS9SXoSJ7TuXzru/HOZ4UhYAEUGeDH+sJo+HVSzXEqMoCrvPpjNrczx/x6cBUNHdkQnP1OPJ+gEym0gIAcCV7AI+/v0ES/YmoCjgbK/j5dbVGdQq1GzG8El5kfIiykGxwcj3O8/zycaTpUtzV/dzZcjD1egSVdmk40sUReHPk6nM3hLP3nMl41p0Wg29mwbzRvswPJ1ltVwhxL8dvpTJhDVHSv9uuDna8WzjIAY0r0pVX1dVs5lFeZk0aRLr1q0jNjYWBwcHMjIy7vgYRVEYP3488+bNIyMjg5YtWzJnzhxq1qx5188r5UWUt5SsfL79+xyLdp0n61qJ8XVzpE/TYNrVC6BeoEeZnQE5nZrNr3GXWXvoculZHwedlueaBPHfR6rLTCIhxB0pisKaQ5eZ8cdJzqSWXGbWaOCx2hXp17wKLar74GhX/oP7zaK8jB8/Hi8vLy5evMg333xzV+Vl6tSpTJkyhQULFhAaGsrYsWOJi4vj6NGjODk53dXzSnkRasnKL2LJngS+3X62dFAvQKCnE4/X8efxOhVpXNX7nk7RZuYVcSo5i+3xV1gfd5kTyVml/+Zsr6NPsxCGPlINf4+7+/0QQojrjEaFv+LTmL/9LFtOpJbe72yv46Fq3jxSy49HavlRzde1XC5Bm0V5uW7+/PmMHDnyjuVFURQCAwMZPXo0r7/+OgCZmZn4+/szf/58evXqdVfPJ+VFqK3IYGTdocusi7vMX6dSyS+6cX8kXzdHQn1dqOrjShUfF+x0WgxGBaNRwaAoZOcXcyolm5PJWTeUIAA7rYaWNXzpGF6JdvX88XIxn5lOQgjLdSY1m+93nmdd3GVSswpu+LcKLvZUruBMoKczgV7OBFVwJtjbhfb1Aso0w728f5vHKB3g7NmzJCUl0bZt29L7PD09adasGTt37rxleSkoKKCg4H8vtF5vG5tSCfNlr9PSJaoyXaIqk19kYMfpNDYeTWHriRQuZ+aTll1AWnZB6TXnOwn0dKJeZU/a1fWnXd0APF1kPIsQomxV83PjvWfqMb5TXY4nZbHtZCrbTqWy9+xVruYWcTW3iMOX/vf+GuztXObl5V6YTXlJSkoCwN/f/4b7/f39S//tZqZMmcKECRNMmk2I++Vkr+OxMH8eCyv57zorv4hzabmcvZLD2dQcEq7mYlQUdBoNdjoNWo0GRzsd1Su6EhbgTk1/dzycpKwIIcqHRqOhTiUP6lTy4L+PViev0MD59BwuXc0jMSOPSxn5XMrIo4LKH6LuqbyMGTOGqVOn3vaYY8eOERYW9kCh7kV0dDSjRo0q/Vqv1xMcLAtyCfPk7mRPeJAn4UGeakcRQog7cnbQERbgQViAeQ3DuKfyMnr0aAYOHHjbY6pVq3ZfQQICSk4/JScnU6lSpdL7k5OTiYyMvOXjHB0dcXR0vK/nFEIIIYTluafy4ufnh5+fn0mChIaGEhAQwKZNm0rLil6vZ/fu3bz00ksmeU4hhBBCWB6tqb7xhQsXiI2N5cKFCxgMBmJjY4mNjSU7O7v0mLCwMFauXAmUXGcbOXIkH3zwAatXryYuLo7+/fsTGBhIly5dTBVTCCGEEBbGZAN2x40bx4IFC0q/joqKAmDLli20bt0agBMnTpCZmVl6zJtvvklOTg5Dhw4lIyODVq1asWHDhrte40UIIYQQ1s/qtgfIzMzEy8uLhIQEWedFCCGEsBDXJ9xkZGTg6Xn7SQ1mM1W6rGRllaxAKjOOhBBCCMuTlZV1x/JidWdejEYjiYmJuLu7l/lyxtdboZzVUYe8/uqS119d8vqrS15/01MUhaysLAIDA9Fqbz8k1+rOvGi1WoKCgkz6HB4eHvIfr4rk9VeXvP7qktdfXfL6m9adzrhcZ7LZRkIIIYQQpiDlRQghhBAWRcrLPXB0dGT8+PGyoq9K5PVXl7z+6pLXX13y+psXqxuwK4QQQgjrJmdehBBCCGFRpLwIIYQQwqJIeRFCCCGERZHyIoQQQgiLIuVFCCGEEBZFystdmj17NlWrVsXJyYlmzZqxZ88etSPZhClTptCkSRPc3d2pWLEiXbp04cSJE2rHslkffvghGo2GkSNHqh3FZly6dIl+/frh4+ODs7Mz4eHh7Nu3T+1YNsFgMDB27FhCQ0NxdnamevXqTJw4EZmkqz4pL3dh6dKljBo1ivHjx7N//34iIiJo3749KSkpakezen/++SfDhg1j165dbNy4kaKiItq1a0dOTo7a0WzO3r17+eqrr2jQoIHaUWzG1atXadmyJfb29vz6668cPXqU6dOnU6FCBbWj2YSpU6cyZ84cZs2axbFjx5g6dSrTpk1j5syZakezebLOy11o1qwZTZo0YdasWUDJ5o/BwcG88sorjBkzRuV0tiU1NZWKFSvy559/8sgjj6gdx2ZkZ2fTsGFDvvjiCz744AMiIyOZMWOG2rGs3pgxY9i+fTt//fWX2lFs0tNPP42/vz/ffPNN6X3du3fH2dmZhQsXqphMyJmXOygsLCQmJoa2bduW3qfVamnbti07d+5UMZltyszMBMDb21vlJLZl2LBhdOzY8YbfA2F6q1evpnHjxjz77LNUrFiRqKgo5s2bp3Ysm9GiRQs2bdrEyZMnATh48CB///03HTp0UDmZsLpdpctaWloaBoMBf3//G+739/fn+PHjKqWyTUajkZEjR9KyZUvq16+vdhybsWTJEvbv38/evXvVjmJzzpw5w5w5cxg1ahRvv/02e/fu5dVXX8XBwYEBAwaoHc/qjRkzBr1eT1hYGDqdDoPBwKRJk+jbt6/a0WyelBdhMYYNG8bhw4f5+++/1Y5iMxISEhgxYgQbN27EyclJ7Tg2x2g00rhxYyZPngxAVFQUhw8f5ssvv5TyUg5++uknFi1axOLFi6lXrx6xsbGMHDmSwMBAef1VJuXlDnx9fdHpdCQnJ99wf3JyMgEBASqlsj3Dhw9n7dq1bNu2jaCgILXj2IyYmBhSUlJo2LBh6X0Gg4Ft27Yxa9YsCgoK0Ol0Kia0bpUqVaJu3bo33FenTh2WL1+uUiLb8sYbbzBmzBh69eoFQHh4OOfPn2fKlClSXlQmY17uwMHBgUaNGrFp06bS+4xGI5s2baJ58+YqJrMNiqIwfPhwVq5cyebNmwkNDVU7kk15/PHHiYuLIzY2tvTWuHFj+vbtS2xsrBQXE2vZsuW/lgY4efIkVapUUSmRbcnNzUWrvfFtUqfTYTQaVUokrpMzL3dh1KhRDBgwgMaNG9O0aVNmzJhBTk4OgwYNUjua1Rs2bBiLFy9m1apVuLu7k5SUBICnpyfOzs4qp7N+7u7u/xpf5Orqio+Pj4w7KgevvfYaLVq0YPLkyTz33HPs2bOHuXPnMnfuXLWj2YROnToxadIkQkJCqFevHgcOHOCTTz7h+eefVzuaUMRdmTlzphISEqI4ODgoTZs2VXbt2qV2JJsA3PT23XffqR3NZj366KPKiBEj1I5hM9asWaPUr19fcXR0VMLCwpS5c+eqHclm6PV6ZcSIEUpISIji5OSkVKtWTXnnnXeUgoICtaPZPFnnRQghhBAWRca8CCGEEMKiSHkRQgghhEWR8iKEEEIIiyLlRQghhBAWRcqLEEIIISyKlBchhBBCWBQpL0IIIYSwKFJehBBCCGFRpLwIIYQQwqJIeRFCCCGERZHyIoQQQgiL8n9gLN/3JTA+3gAAAABJRU5ErkJggg==\n",
      "text/plain": [
       "<Figure size 640x480 with 2 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "x = np.arange(0,  3  * np.pi,  0.1)\n",
    "y_sin = np.sin(x)\n",
    "y_cos = np.cos(x)\n",
    "plt.subplot(2,  1,  1)\n",
    "plt.plot(x, y_sin)\n",
    "plt.title('Sine')\n",
    "plt.subplot(2,  1,  2)\n",
    "plt.plot(x, y_cos)\n",
    "plt.title('Cosine')\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "379ff9c4-67ef-41c4-9fbb-a45f33421c73",
   "metadata": {},
   "source": [
    "## bar()\n",
    "\n",
    ">pyplot 子模块提供 bar() 函数来生成条形图。\n",
    "\n",
    ">以下实例生成两组 x 和 y 数组的条形图。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 322,
   "id": "9c7bdf60-843d-4c39-93ef-cf2d1958923f",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "x =  [5,8,10]\n",
    "y =  [12,16,6]\n",
    "x2 =  [6,9,11]\n",
    "y2 =  [6,15,7]\n",
    "plt.bar(x, y, align='center')\n",
    "plt.bar(x2, y2, color='g', align='center')\n",
    "plt.title('Bar graph')\n",
    "plt.ylabel('Y axis')\n",
    "plt.xlabel('X axis')\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "59a9ae6d-2a03-4b19-9ffd-52929bc0e720",
   "metadata": {},
   "source": [
    "## numpy.histogram()\n",
    "\n",
    ">numpy.histogram() 函数是数据的频率分布的图形表示。 水平尺寸相等的矩形对应于类间隔，称为 bin，变量 height 对应于频率。\n",
    "\n",
    ">numpy.histogram()函数将输入数组和 bin 作为两个参数。 bin 数组中的连续元素用作每个 bin 的边界。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 323,
   "id": "4ef2457b-03ed-4529-aa58-6c5e928b2bde",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[3 4 5 2 1]\n",
      "[  0  20  40  60  80 100]\n"
     ]
    }
   ],
   "source": [
    "a = np.array([22,87,5,43,56,73,55,54,11,20,51,5,79,31,27])\n",
    "np.histogram(a,bins =  [0,20,40,60,80,100])\n",
    "hist,bins = np.histogram(a,bins =  [0,20,40,60,80,100])\n",
    "print (hist)\n",
    "print (bins)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "812a461c-3eee-40d3-9d27-ceb4c2fcd500",
   "metadata": {},
   "source": [
    "## plt()\n",
    "\n",
    ">Matplotlib 可以将直方图的数字表示转换为图形。 pyplot 子模块的 plt() 函数将包含数据和 bin 数组的数组作为参数，并转换为直方图。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 324,
   "id": "538ecca6-107e-4766-b22f-657293fc16b6",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "image/png": "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8R544IF06aWXprvuuitFRJo7d26z21uyp1/5ylfS8OHD0+LFi9N//ud/poMOOiiNGzeuVebdK8Li6KOPTpMnTy5c3759e+rTp0+qqalpw6n2Lhs2bEgRkRYuXJhSSmnz5s1pn332SXfeeWdhzX//93+niEhPPPFEW43ZLm3ZsiUdfPDBaf78+elP//RPC2Fhj/P50Y9+lI4//vhd3t7U1JSqqqrSz372s8KxzZs3p7KysnT77bfviRH3CmPHjk3nnHNOs2Nf//rX0/jx41NK9jmHD4ZFS/Z09erVKSLS0qVLC2vmzZuXSkpK0rp167LP2O7fCnnnnXeitrY2Ro8eXTjWoUOHGD16dDzxxBNtONnepb6+PiIiunfvHhERtbW18e677zbb9yFDhkT//v3te5EmT54cY8eObbaXEfY4p3vvvTdGjhwZ3/zmN6NXr15xxBFHxPXXX1+4/cUXX4z169c32+uKioo45phj7HURvvjFL8aCBQviueeei4iI3/3ud/H444/HmDFjIsI+t4aW7OkTTzwRlZWVMXLkyMKa0aNHR4cOHWLJkiXZZ2r1r01vba+//nps3759hx8p3rt373j22WfbaKq9S1NTU0ybNi2OO+64GDp0aERErF+/Pjp16rTDN9X27t071q9f3wZTtk9z5syJ5cuXx9KlS3e4zR7n88ILL8S1114b06dPj7/5m7+JpUuXxpQpU6JTp04xYcKEwn7u7O8Re91yl1xySTQ0NMSQIUOiY8eOsX379rjqqqti/PjxERH2uRW0ZE/Xr18fvXr1anZ7aWlpdO/evVX2vd2HBa1v8uTJsXLlynj88cfbepS9Sl1dXUydOjXmz58fnTt3butx9mpNTU0xcuTI+PGPfxwREUcccUSsXLkyfv3rX8eECRPaeLq9x29/+9u49dZb47bbbovDDjssVqxYEdOmTYs+ffrY50+Rdv9WSM+ePaNjx447nCn/2muvRVVVVRtNtfe44IIL4r777otHH300+vbtWzheVVUV77zzTmzevLnZevvecrW1tbFhw4Y48sgjo7S0NEpLS2PhwoXxj//4j1FaWhq9e/e2x5kccMABceihhzY7dsghh8TLL78cEVHYT3+PfDwXX3xxXHLJJXHWWWfF4YcfHmeffXb81V/9VdTU1ESEfW4NLdnTqqqq2LBhQ7Pb//jHP8amTZtaZd/bfVh06tQpRowYEQsWLCgca2pqigULFsSoUaPacLL2LaUUF1xwQcydOzceeeSRGDRoULPbR4wYEfvss0+zfV+zZk28/PLL9r2FTj755HjmmWdixYoVhcvIkSNj/Pjxhd/b4zyOO+64HT4u/dxzz8WAAQMiImLQoEFRVVXVbK8bGhpiyZIl9roIb775ZnTo0PyflY4dO0ZTU1NE2OfW0JI9HTVqVGzevDlqa2sLax555JFoamqKY445Jv9Q2U8HbQNz5sxJZWVl6eabb06rV69O5513XqqsrEzr169v69Hare9///upoqIiPfbYY+nVV18tXN58883CmvPPPz/1798/PfLII2nZsmVp1KhRadSoUW04dfv3/k+FpGSPc3nyySdTaWlpuuqqq9Lzzz+fbr311rTvvvumW265pbBm1qxZqbKyMt1zzz3p6aefTmeccYaPQRZpwoQJ6bOf/Wzh46Z33XVX6tmzZ/rrv/7rwhr7XLwtW7akp556Kj311FMpItLVV1+dnnrqqfSHP/whpdSyPf3KV76SjjjiiLRkyZL0+OOPp4MPPtjHTT/KL3/5y9S/f//UqVOndPTRR6fFixe39UjtWkTs9HLTTTcV1rz11lvpBz/4Qdpvv/3Svvvum84888z06quvtt3Qe4EPhoU9zuff//3f09ChQ1NZWVkaMmRI+s1vftPs9qampnTZZZel3r17p7KysnTyySenNWvWtNG07VNDQ0OaOnVq6t+/f+rcuXM68MAD06WXXpoaGxsLa+xz8R599NGd/n08YcKElFLL9nTjxo1p3LhxqWvXrqm8vDxNmjQpbdmypVXmLUnpfT8SDQDgY2j351gAAJ8cwgIAyEZYAADZCAsAIBthAQBkIywAgGyEBQCQjbAAALIRFgBANsICAMhGWAAA2fw/4qkNjLll7iUAAAAASUVORK5CYII=\n",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "a = np.array([22,87,5,43,56,73,55,54,11,20,51,5,79,31,27]) \n",
    "plt.hist(a, bins =  [0,20,40,60,80,100]) \n",
    "plt.title(\"histogram\") \n",
    "plt.show()"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.3"
  },
  "toc-autonumbering": true,
  "toc-showcode": false,
  "toc-showmarkdowntxt": false,
  "toc-showtags": false
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
